mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Compare commits
64 Commits
ba2333069a
...
capella-ho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
962ce28b7b | ||
|
|
5fa1fd84b9 | ||
|
|
bd0c9f9e8d | ||
|
|
2532bb370c | ||
|
|
12efc6c2c1 | ||
|
|
a6cc9ac9c5 | ||
|
|
031f5845a2 | ||
|
|
b88559726c | ||
|
|
62f6b07cba | ||
|
|
f956f1ed6e | ||
|
|
16b0820193 | ||
|
|
4b02267e96 | ||
|
|
746584c453 | ||
|
|
b56daaaca2 | ||
|
|
931e5e10c3 | ||
|
|
c172f838b1 | ||
|
|
c07ae29cd9 | ||
|
|
214c9bfd8b | ||
|
|
716140d64d | ||
|
|
088cb4ef59 | ||
|
|
d1472fc351 | ||
|
|
5c8c0c31d8 | ||
|
|
7f3c00c7a2 | ||
|
|
c180dab791 | ||
|
|
f24acc21c7 | ||
|
|
40b637849d | ||
|
|
e7db1685df | ||
|
|
eccbfd1011 | ||
|
|
90211f6769 | ||
|
|
edc32ac18e | ||
|
|
fe68e020e3 | ||
|
|
81e1e3544d | ||
|
|
09372d5c35 | ||
|
|
078a89e4ca | ||
|
|
dbc6ae26a6 | ||
|
|
b6f429867a | ||
|
|
09f50660ce | ||
|
|
189825b495 | ||
|
|
764b7ff610 | ||
|
|
d499db7f0e | ||
|
|
ed2d1c7bf9 | ||
|
|
14b73cbd47 | ||
|
|
3124785a08 | ||
|
|
60e6306107 | ||
|
|
42ccb7830a | ||
|
|
0bb03b9292 | ||
|
|
ed6fbf1480 | ||
|
|
477cec6021 | ||
|
|
924500d111 | ||
|
|
0677504ef1 | ||
|
|
ca2a7c4d9c | ||
|
|
28606629ad | ||
|
|
c817279464 | ||
|
|
009d6ed8ed | ||
|
|
5cec1282a9 | ||
|
|
340170fd29 | ||
|
|
7ed0cc139a | ||
|
|
2c822213eb | ||
|
|
c08bb39ffe | ||
|
|
5083d8ab34 | ||
|
|
7552a5dd07 | ||
|
|
c93d68f853 | ||
|
|
3e8aa4023d | ||
|
|
b443875e66 |
12
WORKSPACE
12
WORKSPACE
@@ -231,8 +231,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "eded065f923a99b78372d6f748c9b3f1de8229f8f574c1fec9c5fe76c8affb65",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
|
||||
sha256 = "42f66a2b8c139c07843ac2898f2cb61729ea6eb7a080d151e3bac78e207bfe52",
|
||||
urls = ["file:///tmp/general-f5c7cf78.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -247,8 +247,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "2ed83783129e93360f4bf9d5d5f606ee28adbe8b458acdfac61b8d99218d16a9",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
|
||||
sha256 = "ec762b0cede38c8edc93a2c215053fa7834a906004333cd2e2a44a6247e0338b",
|
||||
urls = ["file:///tmp/minimal-f5c7cf78.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -263,8 +263,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "f5eff2adac78c99a4180491f373328465263caa2cba0206308a7c598abf76cda",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
|
||||
sha256 = "2a98e39e5729a2e364492a7b82d710010eaee8f7a4968c91023dd4ae58f7c3d6",
|
||||
urls = ["file:///tmp/mainnet-f5c7cf78.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
)
|
||||
|
||||
var defaultLatestValidHash = bytesutil.PadTo([]byte{0xff}, 32)
|
||||
var errNoAttribute = errors.New("could not get payload attributes")
|
||||
|
||||
// notifyForkchoiceUpdateArg is the argument for the forkchoice update notification `notifyForkchoiceUpdate`.
|
||||
type notifyForkchoiceUpdateArg struct {
|
||||
@@ -32,6 +33,58 @@ type notifyForkchoiceUpdateArg struct {
|
||||
headBlock interfaces.BeaconBlock
|
||||
}
|
||||
|
||||
type callForkchoiceUpdatedReturn struct {
|
||||
hasAttr bool
|
||||
proposerId types.ValidatorIndex
|
||||
payloadID *enginev1.PayloadIDBytes
|
||||
lastValidHash []byte
|
||||
err error
|
||||
}
|
||||
|
||||
// callFforkchoiceUpdatedV1 wraps a call to the engine methods `engine_forkchoiceUpdatedV1`
|
||||
func (s *Service) callForkchoiceUpdatedV1(
|
||||
ctx context.Context,
|
||||
st state.BeaconState,
|
||||
nextSlot types.Slot,
|
||||
fcs *enginev1.ForkchoiceState) callForkchoiceUpdatedReturn {
|
||||
|
||||
hasAttr, attr, proposerId, err := s.getPayloadAttribute(ctx, st, nextSlot)
|
||||
if err != nil {
|
||||
return callForkchoiceUpdatedReturn{false, 0, nil, nil, errNoAttribute}
|
||||
}
|
||||
|
||||
payloadID, lastValidHash, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, attr)
|
||||
return callForkchoiceUpdatedReturn{
|
||||
hasAttr: hasAttr,
|
||||
proposerId: proposerId,
|
||||
payloadID: payloadID,
|
||||
lastValidHash: lastValidHash,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// callFforkchoiceUpdatedV2 wraps a call to the engine methods `engine_forkchoiceUpdatedV2`
|
||||
func (s *Service) callForkchoiceUpdatedV2(
|
||||
ctx context.Context,
|
||||
st state.BeaconState,
|
||||
nextSlot types.Slot,
|
||||
fcs *enginev1.ForkchoiceState) callForkchoiceUpdatedReturn {
|
||||
|
||||
hasAttr, attr, proposerId, err := s.getPayloadAttributeV2(ctx, st, nextSlot)
|
||||
if err != nil {
|
||||
return callForkchoiceUpdatedReturn{false, 0, nil, nil, errNoAttribute}
|
||||
}
|
||||
|
||||
payloadID, lastValidHash, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdatedV2(ctx, fcs, attr)
|
||||
return callForkchoiceUpdatedReturn{
|
||||
hasAttr: hasAttr,
|
||||
proposerId: proposerId,
|
||||
payloadID: payloadID,
|
||||
lastValidHash: lastValidHash,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// notifyForkchoiceUpdate signals execution engine the fork choice updates. Execution engine should:
|
||||
// 1. Re-organizes the execution payload chain and corresponding state to make head_block_hash the head.
|
||||
// 2. Applies finality to the execution state: it irreversibly persists the chain of all execution payloads and corresponding state, up to and including finalized_block_hash.
|
||||
@@ -67,15 +120,16 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
}
|
||||
|
||||
nextSlot := s.CurrentSlot() + 1 // Cache payload ID for next slot proposer.
|
||||
hasAttr, attr, proposerId, err := s.getPayloadAttribute(ctx, arg.headState, nextSlot)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get head payload attribute")
|
||||
return nil, nil
|
||||
var fcuReturn callForkchoiceUpdatedReturn
|
||||
if slots.ToEpoch(nextSlot) >= params.BeaconConfig().CapellaForkEpoch {
|
||||
fcuReturn = s.callForkchoiceUpdatedV2(ctx, arg.headState, nextSlot, fcs)
|
||||
} else {
|
||||
fcuReturn = s.callForkchoiceUpdatedV1(ctx, arg.headState, nextSlot, fcs)
|
||||
}
|
||||
|
||||
payloadID, lastValidHash, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, attr)
|
||||
if err != nil {
|
||||
switch err {
|
||||
if fcuReturn.err != nil {
|
||||
switch fcuReturn.err {
|
||||
case errNoAttribute:
|
||||
return nil, errNoAttribute
|
||||
case execution.ErrAcceptedSyncingPayloadStatus:
|
||||
forkchoiceUpdatedOptimisticNodeCount.Inc()
|
||||
log.WithFields(logrus.Fields{
|
||||
@@ -83,14 +137,14 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
"headPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(headPayload.BlockHash())),
|
||||
"finalizedPayloadBlockHash": fmt.Sprintf("%#x", bytesutil.Trunc(finalizedHash[:])),
|
||||
}).Info("Called fork choice updated with optimistic block")
|
||||
return payloadID, nil
|
||||
return fcuReturn.payloadID, nil
|
||||
case execution.ErrInvalidPayloadStatus:
|
||||
forkchoiceUpdatedInvalidNodeCount.Inc()
|
||||
headRoot := arg.headRoot
|
||||
if len(lastValidHash) == 0 {
|
||||
lastValidHash = defaultLatestValidHash
|
||||
if len(fcuReturn.lastValidHash) == 0 {
|
||||
fcuReturn.lastValidHash = defaultLatestValidHash
|
||||
}
|
||||
invalidRoots, err := s.ForkChoicer().SetOptimisticToInvalid(ctx, headRoot, headBlk.ParentRoot(), bytesutil.ToBytes32(lastValidHash))
|
||||
invalidRoots, err := s.ForkChoicer().SetOptimisticToInvalid(ctx, headRoot, headBlk.ParentRoot(), bytesutil.ToBytes32(fcuReturn.lastValidHash))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not set head root to invalid")
|
||||
return nil, nil
|
||||
@@ -150,17 +204,23 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
||||
log.WithError(err).Error("Could not set head root to valid")
|
||||
return nil, nil
|
||||
}
|
||||
if hasAttr && payloadID != nil { // If the forkchoice update call has an attribute, update the proposer payload ID cache.
|
||||
// If the forkchoice update call has an attribute, update the proposer payload ID cache.
|
||||
if fcuReturn.hasAttr && fcuReturn.payloadID != nil {
|
||||
var pId [8]byte
|
||||
copy(pId[:], payloadID[:])
|
||||
s.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nextSlot, proposerId, pId, arg.headRoot)
|
||||
} else if hasAttr && payloadID == nil {
|
||||
copy(pId[:], fcuReturn.payloadID[:])
|
||||
s.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(
|
||||
nextSlot,
|
||||
fcuReturn.proposerId,
|
||||
pId,
|
||||
arg.headRoot,
|
||||
)
|
||||
} else if fcuReturn.hasAttr && fcuReturn.payloadID == nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"blockHash": fmt.Sprintf("%#x", headPayload.BlockHash()),
|
||||
"slot": headBlk.Slot(),
|
||||
}).Error("Received nil payload ID on VALID engine response")
|
||||
}
|
||||
return payloadID, nil
|
||||
return fcuReturn.payloadID, nil
|
||||
}
|
||||
|
||||
// getPayloadHash returns the payload hash given the block root.
|
||||
@@ -302,6 +362,68 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
||||
return true, attr, proposerID, nil
|
||||
}
|
||||
|
||||
// getPayloadAttributesV2 returns the payload attributes for the given state and slot.
|
||||
// The attribute is required to initiate a payload build process in the context of an `engine_forkchoiceUpdatedV2` call.
|
||||
func (s *Service) getPayloadAttributeV2(
|
||||
ctx context.Context,
|
||||
st state.BeaconState,
|
||||
slot types.Slot) (bool, *enginev1.PayloadAttributesV2, types.ValidatorIndex, error) {
|
||||
// Root is `[32]byte{}` since we are retrieving proposer ID of a given slot.
|
||||
// During insertion at assignment the root was not known.
|
||||
proposerID, _, ok := s.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, [32]byte{} /* root */)
|
||||
if !ok { // There's no need to build attribute if there is no proposer for slot.
|
||||
return false, nil, 0, nil
|
||||
}
|
||||
|
||||
// Get previous randao.
|
||||
st = st.Copy()
|
||||
st, err := transition.ProcessSlotsIfPossible(ctx, st, slot)
|
||||
if err != nil {
|
||||
return false, nil, 0, err
|
||||
}
|
||||
prevRando, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
|
||||
if err != nil {
|
||||
return false, nil, 0, nil
|
||||
}
|
||||
|
||||
// Get fee recipient.
|
||||
feeRecipient := params.BeaconConfig().DefaultFeeRecipient
|
||||
recipient, err := s.cfg.BeaconDB.FeeRecipientByValidatorID(ctx, proposerID)
|
||||
switch {
|
||||
case errors.Is(err, kv.ErrNotFoundFeeRecipient):
|
||||
if feeRecipient.String() == params.BeaconConfig().EthBurnAddressHex {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"validatorIndex": proposerID,
|
||||
"burnAddress": params.BeaconConfig().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")
|
||||
}
|
||||
case err != nil:
|
||||
return false, nil, 0, errors.Wrap(err, "could not get fee recipient in db")
|
||||
default:
|
||||
feeRecipient = recipient
|
||||
}
|
||||
|
||||
// Get timestamp.
|
||||
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
|
||||
if err != nil {
|
||||
return false, nil, 0, err
|
||||
}
|
||||
withdrawals, err := st.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
return false, nil, 0, errors.Wrap(err, "could not get expected withdrawals")
|
||||
}
|
||||
attr := &enginev1.PayloadAttributesV2{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
PrevRandao: prevRando,
|
||||
SuggestedFeeRecipient: feeRecipient.Bytes(),
|
||||
Withdrawals: withdrawals,
|
||||
}
|
||||
return true, attr, proposerID, nil
|
||||
}
|
||||
|
||||
// removeInvalidBlockAndState removes the invalid block and its corresponding state from the cache and DB.
|
||||
func (s *Service) removeInvalidBlockAndState(ctx context.Context, blkRoots [][32]byte) error {
|
||||
for _, root := range blkRoots {
|
||||
|
||||
@@ -117,12 +117,20 @@ func logPayload(block interfaces.BeaconBlock) error {
|
||||
return errors.New("gas limit should not be 0")
|
||||
}
|
||||
gasUtilized := float64(payload.GasUsed()) / float64(payload.GasLimit())
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
fields := logrus.Fields{
|
||||
"blockHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.BlockHash())),
|
||||
"parentHash": fmt.Sprintf("%#x", bytesutil.Trunc(payload.ParentHash())),
|
||||
"blockNumber": payload.BlockNumber,
|
||||
"gasUtilized": fmt.Sprintf("%.2f", gasUtilized),
|
||||
}).Debug("Synced new payload")
|
||||
}
|
||||
if block.Version() >= version.Capella {
|
||||
withdrawals, err := payload.Withdrawals()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get withdrawals")
|
||||
}
|
||||
fields["withdrawals"] = len(withdrawals)
|
||||
}
|
||||
|
||||
log.WithFields(fields).Debug("Synced new payload")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ func reportEpochMetrics(ctx context.Context, postState, headState state.BeaconSt
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case version.Altair, version.Bellatrix:
|
||||
case version.Altair, version.Bellatrix, version.Capella:
|
||||
v, b, err = altair.InitializePrecomputeValidators(ctx, headState)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -69,6 +69,7 @@ func (s *Service) verifyBlkPreState(ctx context.Context, b interfaces.BeaconBloc
|
||||
// during initial syncing. There's no risk given a state summary object is just a
|
||||
// a subset of the block object.
|
||||
if !s.cfg.BeaconDB.HasStateSummary(ctx, parentRoot) && !s.cfg.BeaconDB.HasBlock(ctx, parentRoot) {
|
||||
log.Errorf("requesting blockroot %#x", bytesutil.Trunc(parentRoot[:]))
|
||||
return errors.New("could not reconstruct parent state")
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ func (c *SyncCommitteeHeadStateCache) Get(slot types.Slot) (state.BeaconState, e
|
||||
return nil, ErrIncorrectType
|
||||
}
|
||||
switch st.Version() {
|
||||
case version.Altair, version.Bellatrix:
|
||||
case version.Altair, version.Bellatrix, version.Capella:
|
||||
default:
|
||||
return nil, ErrIncorrectType
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload interfaces.
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(payload.ParentHash(), header.BlockHash()) {
|
||||
log.Errorf("parent Hash %#x, header Hash: %#x", bytesutil.Trunc(payload.ParentHash()), bytesutil.Trunc(header.BlockHash()))
|
||||
return ErrInvalidPayloadBlockHash
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -124,6 +124,7 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
|
||||
return nil, errInvalidWithdrawalIndex
|
||||
}
|
||||
if withdrawal.ValidatorIndex != expected[i].ValidatorIndex {
|
||||
log.Errorf("Expected %v, got %v", expected[i], withdrawal)
|
||||
return nil, errInvalidValidatorIndex
|
||||
}
|
||||
if !bytes.Equal(withdrawal.ExecutionAddress, expected[i].ExecutionAddress) {
|
||||
|
||||
@@ -28,10 +28,16 @@ import (
|
||||
const (
|
||||
// NewPayloadMethod v1 request string for JSON-RPC.
|
||||
NewPayloadMethod = "engine_newPayloadV1"
|
||||
// NewPayloadMethod v2 request string for JSON-RPC.
|
||||
NewPayloadMethodV2 = "engine_newPayloadV2"
|
||||
// ForkchoiceUpdatedMethod v1 request string for JSON-RPC.
|
||||
ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1"
|
||||
// ForkchoiceUpdatedMethod v2 request string for JSON-RPC.
|
||||
ForkchoiceUpdatedMethodV2 = "engine_forkchoiceUpdatedV2"
|
||||
// GetPayloadMethod v1 request string for JSON-RPC.
|
||||
GetPayloadMethod = "engine_getPayloadV1"
|
||||
// GetPayloadMethod v2 request string for JSON-RPC.
|
||||
GetPayloadMethodV2 = "engine_getPayloadV2"
|
||||
// ExchangeTransitionConfigurationMethod v1 request string for JSON-RPC.
|
||||
ExchangeTransitionConfigurationMethod = "engine_exchangeTransitionConfigurationV1"
|
||||
// ExecutionBlockByHashMethod request string for JSON-RPC.
|
||||
@@ -68,7 +74,11 @@ type EngineCaller interface {
|
||||
ForkchoiceUpdated(
|
||||
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributes,
|
||||
) (*pb.PayloadIDBytes, []byte, error)
|
||||
ForkchoiceUpdatedV2(
|
||||
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributesV2,
|
||||
) (*pb.PayloadIDBytes, []byte, error)
|
||||
GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error)
|
||||
GetPayloadV2(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayloadCapella, error)
|
||||
ExchangeTransitionConfiguration(
|
||||
ctx context.Context, cfg *pb.TransitionConfiguration,
|
||||
) error
|
||||
@@ -89,13 +99,21 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &pb.PayloadStatus{}
|
||||
payloadPb, ok := payload.Proto().(*pb.ExecutionPayload)
|
||||
payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadCapella)
|
||||
if !ok {
|
||||
return nil, errors.New("execution data must be an execution payload")
|
||||
}
|
||||
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payloadPb)
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
payloadPb, ok := payload.Proto().(*pb.ExecutionPayload)
|
||||
if !ok {
|
||||
return nil, errors.New("execution data must be a Bellatrix or Capella execution payload")
|
||||
}
|
||||
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payloadPb)
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
}
|
||||
} else {
|
||||
err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV2, payloadPb)
|
||||
if err != nil {
|
||||
return nil, handleRPCError(err)
|
||||
}
|
||||
}
|
||||
|
||||
switch result.Status {
|
||||
@@ -148,6 +166,42 @@ func (s *Service) ForkchoiceUpdated(
|
||||
}
|
||||
}
|
||||
|
||||
// ForkchoiceUpdatedV2 calls the engine_forkchoiceUpdatedV2 method via JSON-RPC.
|
||||
func (s *Service) ForkchoiceUpdatedV2(
|
||||
ctx context.Context, state *pb.ForkchoiceState, attrs *pb.PayloadAttributesV2,
|
||||
) (*pb.PayloadIDBytes, []byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ForkchoiceUpdatedV2")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
forkchoiceUpdatedLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
d := time.Now().Add(time.Duration(params.BeaconConfig().ExecutionEngineTimeoutValue) * time.Second)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &ForkchoiceUpdatedResponse{}
|
||||
err := s.rpcClient.CallContext(ctx, result, ForkchoiceUpdatedMethodV2, state, attrs)
|
||||
if err != nil {
|
||||
return nil, nil, handleRPCError(err)
|
||||
}
|
||||
|
||||
if result.Status == nil {
|
||||
return nil, nil, ErrNilResponse
|
||||
}
|
||||
resp := result.Status
|
||||
switch resp.Status {
|
||||
case pb.PayloadStatus_SYNCING:
|
||||
return nil, nil, ErrAcceptedSyncingPayloadStatus
|
||||
case pb.PayloadStatus_INVALID:
|
||||
return nil, resp.LatestValidHash, ErrInvalidPayloadStatus
|
||||
case pb.PayloadStatus_VALID:
|
||||
return result.PayloadId, resp.LatestValidHash, nil
|
||||
default:
|
||||
return nil, nil, ErrUnknownPayloadStatus
|
||||
}
|
||||
}
|
||||
|
||||
// GetPayload calls the engine_getPayloadV1 method via JSON-RPC.
|
||||
func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayload, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetPayload")
|
||||
@@ -165,6 +219,23 @@ func (s *Service) GetPayload(ctx context.Context, payloadId [8]byte) (*pb.Execut
|
||||
return result, handleRPCError(err)
|
||||
}
|
||||
|
||||
// GetPayloadV2 calls the engine_getPayloadV2 method via JSON-RPC.
|
||||
func (s *Service) GetPayloadV2(ctx context.Context, payloadId [8]byte) (*pb.ExecutionPayloadCapella, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetPayloadV2")
|
||||
defer span.End()
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
getPayloadLatency.Observe(float64(time.Since(start).Milliseconds()))
|
||||
}()
|
||||
|
||||
d := time.Now().Add(defaultEngineTimeout)
|
||||
ctx, cancel := context.WithDeadline(ctx, d)
|
||||
defer cancel()
|
||||
result := &pb.ExecutionPayloadCapella{}
|
||||
err := s.rpcClient.CallContext(ctx, result, GetPayloadMethodV2, pb.PayloadIDBytes(payloadId))
|
||||
return result, handleRPCError(err)
|
||||
}
|
||||
|
||||
// ExchangeTransitionConfiguration calls the engine_exchangeTransitionConfigurationV1 method via JSON-RPC.
|
||||
func (s *Service) ExchangeTransitionConfiguration(
|
||||
ctx context.Context, cfg *pb.TransitionConfiguration,
|
||||
|
||||
@@ -814,6 +814,7 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
AttestationsPool: b.attestationPool,
|
||||
ExitPool: b.exitPool,
|
||||
SlashingsPool: b.slashingsPool,
|
||||
BLSChangesPool: b.blsToExecPool,
|
||||
SlashingChecker: slasherService,
|
||||
SyncCommitteeObjectPool: b.syncCommitteePool,
|
||||
ExecutionChainService: web3Service,
|
||||
|
||||
@@ -38,16 +38,9 @@ func TestPendingBLSToExecChanges(t *testing.T) {
|
||||
func TestBLSToExecChangesForInclusion(t *testing.T) {
|
||||
t.Run("empty pool", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
for i := uint64(0); i < params.BeaconConfig().MaxBlsToExecutionChanges-1; i++ {
|
||||
pool.InsertBLSToExecChange(ð.SignedBLSToExecutionChange{
|
||||
Message: ð.BLSToExecutionChange{
|
||||
ValidatorIndex: types.ValidatorIndex(i),
|
||||
},
|
||||
})
|
||||
}
|
||||
changes, err := pool.BLSToExecChangesForInclusion()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(params.BeaconConfig().MaxBlsToExecutionChanges-1), len(changes))
|
||||
assert.Equal(t, 0, len(changes))
|
||||
})
|
||||
t.Run("MaxBlsToExecutionChanges in pool", func(t *testing.T) {
|
||||
pool := NewPool()
|
||||
|
||||
@@ -19,6 +19,7 @@ go_library(
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/execution:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
|
||||
@@ -269,8 +269,10 @@ func setInitialPublishBlockPostRequest(endpoint *apimiddleware.Endpoint,
|
||||
endpoint.PostRequest = &SignedBeaconBlockContainerJson{}
|
||||
} else if currentEpoch < params.BeaconConfig().BellatrixForkEpoch {
|
||||
endpoint.PostRequest = &SignedBeaconBlockAltairContainerJson{}
|
||||
} else {
|
||||
} else if currentEpoch < params.BeaconConfig().CapellaForkEpoch {
|
||||
endpoint.PostRequest = &SignedBeaconBlockBellatrixContainerJson{}
|
||||
} else {
|
||||
endpoint.PostRequest = &SignedBeaconBlockCapellaContainerJson{}
|
||||
}
|
||||
req.Body = io.NopCloser(bytes.NewBuffer(buf))
|
||||
return true, nil
|
||||
|
||||
@@ -350,6 +350,7 @@ type SignedBeaconBlockContainerV2Json struct {
|
||||
Phase0Block *BeaconBlockJson `json:"phase0_block"`
|
||||
AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
|
||||
BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
@@ -357,6 +358,7 @@ type SignedBlindedBeaconBlockContainerJson struct {
|
||||
Phase0Block *BeaconBlockJson `json:"phase0_block"`
|
||||
AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
|
||||
BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
@@ -364,12 +366,14 @@ type BeaconBlockContainerV2Json struct {
|
||||
Phase0Block *BeaconBlockJson `json:"phase0_block"`
|
||||
AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
|
||||
BellatrixBlock *BeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
CapellaBlock *BeaconBlockCapellaJson `json:"capella_block"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockContainerJson struct {
|
||||
Phase0Block *BeaconBlockJson `json:"phase0_block"`
|
||||
AltairBlock *BeaconBlockAltairJson `json:"altair_block"`
|
||||
BellatrixBlock *BlindedBeaconBlockBellatrixJson `json:"bellatrix_block"`
|
||||
CapellaBlock *BlindedBeaconBlockCapellaJson `json:"capella_block"`
|
||||
}
|
||||
|
||||
type SignedBeaconBlockAltairContainerJson struct {
|
||||
@@ -382,11 +386,21 @@ type SignedBeaconBlockBellatrixContainerJson struct {
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type SignedBeaconBlockCapellaContainerJson struct {
|
||||
Message *BeaconBlockCapellaJson `json:"message"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type SignedBlindedBeaconBlockBellatrixContainerJson struct {
|
||||
Message *BlindedBeaconBlockBellatrixJson `json:"message"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type SignedBlindedBeaconBlockCapellaContainerJson struct {
|
||||
Message *BlindedBeaconBlockCapellaJson `json:"message"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type BeaconBlockAltairJson struct {
|
||||
Slot string `json:"slot"`
|
||||
ProposerIndex string `json:"proposer_index"`
|
||||
@@ -403,6 +417,14 @@ type BeaconBlockBellatrixJson struct {
|
||||
Body *BeaconBlockBodyBellatrixJson `json:"body"`
|
||||
}
|
||||
|
||||
type BeaconBlockCapellaJson struct {
|
||||
Slot string `json:"slot"`
|
||||
ProposerIndex string `json:"proposer_index"`
|
||||
ParentRoot string `json:"parent_root" hex:"true"`
|
||||
StateRoot string `json:"state_root" hex:"true"`
|
||||
Body *BeaconBlockBodyCapellaJson `json:"body"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockBellatrixJson struct {
|
||||
Slot string `json:"slot"`
|
||||
ProposerIndex string `json:"proposer_index"`
|
||||
@@ -411,6 +433,14 @@ type BlindedBeaconBlockBellatrixJson struct {
|
||||
Body *BlindedBeaconBlockBodyBellatrixJson `json:"body"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockCapellaJson struct {
|
||||
Slot string `json:"slot"`
|
||||
ProposerIndex string `json:"proposer_index"`
|
||||
ParentRoot string `json:"parent_root" hex:"true"`
|
||||
StateRoot string `json:"state_root" hex:"true"`
|
||||
Body *BlindedBeaconBlockBodyCapellaJson `json:"body"`
|
||||
}
|
||||
|
||||
type BeaconBlockBodyAltairJson struct {
|
||||
RandaoReveal string `json:"randao_reveal" hex:"true"`
|
||||
Eth1Data *Eth1DataJson `json:"eth1_data"`
|
||||
@@ -436,6 +466,20 @@ type BeaconBlockBodyBellatrixJson struct {
|
||||
ExecutionPayload *ExecutionPayloadJson `json:"execution_payload"`
|
||||
}
|
||||
|
||||
type BeaconBlockBodyCapellaJson struct {
|
||||
RandaoReveal string `json:"randao_reveal" hex:"true"`
|
||||
Eth1Data *Eth1DataJson `json:"eth1_data"`
|
||||
Graffiti string `json:"graffiti" hex:"true"`
|
||||
ProposerSlashings []*ProposerSlashingJson `json:"proposer_slashings"`
|
||||
AttesterSlashings []*AttesterSlashingJson `json:"attester_slashings"`
|
||||
Attestations []*AttestationJson `json:"attestations"`
|
||||
Deposits []*DepositJson `json:"deposits"`
|
||||
VoluntaryExits []*SignedVoluntaryExitJson `json:"voluntary_exits"`
|
||||
SyncAggregate *SyncAggregateJson `json:"sync_aggregate"`
|
||||
ExecutionPayload *ExecutionPayloadCapellaJson `json:"execution_payload"`
|
||||
BLSToExecutionChanges []*BLSToExecutionChangeJson `json:"bls_to_execution_changes"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockBodyBellatrixJson struct {
|
||||
RandaoReveal string `json:"randao_reveal" hex:"true"`
|
||||
Eth1Data *Eth1DataJson `json:"eth1_data"`
|
||||
@@ -449,6 +493,20 @@ type BlindedBeaconBlockBodyBellatrixJson struct {
|
||||
ExecutionPayloadHeader *ExecutionPayloadHeaderJson `json:"execution_payload_header"`
|
||||
}
|
||||
|
||||
type BlindedBeaconBlockBodyCapellaJson struct {
|
||||
RandaoReveal string `json:"randao_reveal" hex:"true"`
|
||||
Eth1Data *Eth1DataJson `json:"eth1_data"`
|
||||
Graffiti string `json:"graffiti" hex:"true"`
|
||||
ProposerSlashings []*ProposerSlashingJson `json:"proposer_slashings"`
|
||||
AttesterSlashings []*AttesterSlashingJson `json:"attester_slashings"`
|
||||
Attestations []*AttestationJson `json:"attestations"`
|
||||
Deposits []*DepositJson `json:"deposits"`
|
||||
VoluntaryExits []*SignedVoluntaryExitJson `json:"voluntary_exits"`
|
||||
SyncAggregate *SyncAggregateJson `json:"sync_aggregate"`
|
||||
ExecutionPayloadHeader *ExecutionPayloadHeaderCapellaJson `json:"execution_payload_header"`
|
||||
BLSToExecutionChanges []*BLSToExecutionChangeJson `json:"bls_to_execution_changes"`
|
||||
}
|
||||
|
||||
type ExecutionPayloadJson struct {
|
||||
ParentHash string `json:"parent_hash" hex:"true"`
|
||||
FeeRecipient string `json:"fee_recipient" hex:"true"`
|
||||
@@ -466,6 +524,24 @@ type ExecutionPayloadJson struct {
|
||||
Transactions []string `json:"transactions" hex:"true"`
|
||||
}
|
||||
|
||||
type ExecutionPayloadCapellaJson struct {
|
||||
ParentHash string `json:"parent_hash" hex:"true"`
|
||||
FeeRecipient string `json:"fee_recipient" hex:"true"`
|
||||
StateRoot string `json:"state_root" hex:"true"`
|
||||
ReceiptsRoot string `json:"receipts_root" hex:"true"`
|
||||
LogsBloom string `json:"logs_bloom" hex:"true"`
|
||||
PrevRandao string `json:"prev_randao" hex:"true"`
|
||||
BlockNumber string `json:"block_number"`
|
||||
GasLimit string `json:"gas_limit"`
|
||||
GasUsed string `json:"gas_used"`
|
||||
TimeStamp string `json:"timestamp"`
|
||||
ExtraData string `json:"extra_data" hex:"true"`
|
||||
BaseFeePerGas string `json:"base_fee_per_gas" uint256:"true"`
|
||||
BlockHash string `json:"block_hash" hex:"true"`
|
||||
Transactions []string `json:"transactions" hex:"true"`
|
||||
Withdrawals []*WithdrawalJson `json:"withdrawals"`
|
||||
}
|
||||
|
||||
type ExecutionPayloadHeaderJson struct {
|
||||
ParentHash string `json:"parent_hash" hex:"true"`
|
||||
FeeRecipient string `json:"fee_recipient" hex:"true"`
|
||||
@@ -483,6 +559,24 @@ type ExecutionPayloadHeaderJson struct {
|
||||
TransactionsRoot string `json:"transactions_root" hex:"true"`
|
||||
}
|
||||
|
||||
type ExecutionPayloadHeaderCapellaJson struct {
|
||||
ParentHash string `json:"parent_hash" hex:"true"`
|
||||
FeeRecipient string `json:"fee_recipient" hex:"true"`
|
||||
StateRoot string `json:"state_root" hex:"true"`
|
||||
ReceiptsRoot string `json:"receipts_root" hex:"true"`
|
||||
LogsBloom string `json:"logs_bloom" hex:"true"`
|
||||
PrevRandao string `json:"prev_randao" hex:"true"`
|
||||
BlockNumber string `json:"block_number"`
|
||||
GasLimit string `json:"gas_limit"`
|
||||
GasUsed string `json:"gas_used"`
|
||||
TimeStamp string `json:"timestamp"`
|
||||
ExtraData string `json:"extra_data" 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"`
|
||||
WithdrawalsRoot string `json:"withdrawals_root" hex:"true"`
|
||||
}
|
||||
|
||||
type SyncAggregateJson struct {
|
||||
SyncCommitteeBits string `json:"sync_committee_bits" hex:"true"`
|
||||
SyncCommitteeSignature string `json:"sync_committee_signature" hex:"true"`
|
||||
@@ -553,6 +647,17 @@ type AttestationDataJson struct {
|
||||
Target *CheckpointJson `json:"target"`
|
||||
}
|
||||
|
||||
type BLSToExecutionChangeJson struct {
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
FromBLSPubkey string `json:"from_bls_pubkey" hex:"true"`
|
||||
ToExecutionAddress string `jston:"to_execution_address" hex:"true"`
|
||||
}
|
||||
|
||||
type SigledBLSToExecutionChangeJson struct {
|
||||
BLSToExecutionChange *BLSToExecutionChangeJson `json:"message"`
|
||||
Signature string `json:"signature" hex:"true"`
|
||||
}
|
||||
|
||||
type DepositJson struct {
|
||||
Proof []string `json:"proof" hex:"true"`
|
||||
Data *Deposit_DataJson `json:"data"`
|
||||
@@ -607,6 +712,13 @@ type VersionJson struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type WithdrawalJson struct {
|
||||
WithdrawalIndex string `json:"index"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
ExecutionAddress string `json:"address" hex:"true"`
|
||||
Amount string `json:"amount"`
|
||||
}
|
||||
|
||||
type BeaconStateJson struct {
|
||||
GenesisTime string `json:"genesis_time"`
|
||||
GenesisValidatorsRoot string `json:"genesis_validators_root" hex:"true"`
|
||||
@@ -686,10 +798,41 @@ type BeaconStateBellatrixJson struct {
|
||||
LatestExecutionPayloadHeader *ExecutionPayloadHeaderJson `json:"latest_execution_payload_header"`
|
||||
}
|
||||
|
||||
type BeaconStateCapellaJson struct {
|
||||
GenesisTime string `json:"genesis_time"`
|
||||
GenesisValidatorsRoot string `json:"genesis_validators_root" hex:"true"`
|
||||
Slot string `json:"slot"`
|
||||
Fork *ForkJson `json:"fork"`
|
||||
LatestBlockHeader *BeaconBlockHeaderJson `json:"latest_block_header"`
|
||||
BlockRoots []string `json:"block_roots" hex:"true"`
|
||||
StateRoots []string `json:"state_roots" hex:"true"`
|
||||
HistoricalRoots []string `json:"historical_roots" hex:"true"`
|
||||
Eth1Data *Eth1DataJson `json:"eth1_data"`
|
||||
Eth1DataVotes []*Eth1DataJson `json:"eth1_data_votes"`
|
||||
Eth1DepositIndex string `json:"eth1_deposit_index"`
|
||||
Validators []*ValidatorJson `json:"validators"`
|
||||
Balances []string `json:"balances"`
|
||||
RandaoMixes []string `json:"randao_mixes" hex:"true"`
|
||||
Slashings []string `json:"slashings"`
|
||||
PreviousEpochParticipation EpochParticipation `json:"previous_epoch_participation"`
|
||||
CurrentEpochParticipation EpochParticipation `json:"current_epoch_participation"`
|
||||
JustificationBits string `json:"justification_bits" hex:"true"`
|
||||
PreviousJustifiedCheckpoint *CheckpointJson `json:"previous_justified_checkpoint"`
|
||||
CurrentJustifiedCheckpoint *CheckpointJson `json:"current_justified_checkpoint"`
|
||||
FinalizedCheckpoint *CheckpointJson `json:"finalized_checkpoint"`
|
||||
InactivityScores []string `json:"inactivity_scores"`
|
||||
CurrentSyncCommittee *SyncCommitteeJson `json:"current_sync_committee"`
|
||||
NextSyncCommittee *SyncCommitteeJson `json:"next_sync_committee"`
|
||||
LatestExecutionPayloadHeader *ExecutionPayloadHeaderCapellaJson `json:"latest_execution_payload_header"`
|
||||
NextWithdrawalIndex string `json:"next_withdrawal_index"`
|
||||
LastWithdrawalValidatorIndex string `json:"latest_withdrawal_validator_index"`
|
||||
}
|
||||
|
||||
type BeaconStateContainerV2Json struct {
|
||||
Phase0State *BeaconStateJson `json:"phase0_state"`
|
||||
AltairState *BeaconStateAltairJson `json:"altair_state"`
|
||||
BellatrixState *BeaconStateBellatrixJson `json:"bellatrix_state"`
|
||||
CapellaState *BeaconStateCapellaJson `json:"capella_state"`
|
||||
}
|
||||
|
||||
type ForkJson struct {
|
||||
|
||||
@@ -16,6 +16,7 @@ go_library(
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p"
|
||||
v1alpha1validator "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/prysm/v1alpha1/validator"
|
||||
@@ -24,6 +25,7 @@ type Server struct {
|
||||
StateFetcher statefetcher.Fetcher
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
SyncCommitteePool synccommittee.Pool
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
V1Alpha1Server *v1alpha1validator.Server
|
||||
ProposerSlotIndexCache *cache.ProposerPayloadIDsCache
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ go_library(
|
||||
"//beacon-chain/execution:go_default_library",
|
||||
"//beacon-chain/operations/attestations:go_default_library",
|
||||
"//beacon-chain/operations/slashings:go_default_library",
|
||||
"//beacon-chain/operations/blstoexec:go_default_library",
|
||||
"//beacon-chain/operations/synccommittee:go_default_library",
|
||||
"//beacon-chain/operations/voluntaryexits:go_default_library",
|
||||
"//beacon-chain/p2p:go_default_library",
|
||||
|
||||
@@ -35,8 +35,8 @@ var eth1DataNotification bool
|
||||
const eth1dataTimeout = 2 * time.Second
|
||||
|
||||
// GetBeaconBlock is called by a proposer during its assigned slot to request a block to sign
|
||||
// by passing in the slot and the signed randao reveal of the slot. Returns phase0 beacon blocks
|
||||
// before the Altair fork epoch and Altair blocks post-fork epoch.
|
||||
// by passing in the slot and the signed randao reveal of the slot. Returns a full block
|
||||
// corresponding to the fork epoch
|
||||
func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBeaconBlock")
|
||||
defer span.End()
|
||||
@@ -59,7 +59,6 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
|
||||
if err := vs.optimisticStatus(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vs.getBellatrixBeaconBlock(ctx, req)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,26 +15,12 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
func (vs *Server) BuildAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.BuildAltairBeaconBlock")
|
||||
defer span.End()
|
||||
blkData, err := vs.buildPhase0BlockData(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not build block data: %v", err)
|
||||
}
|
||||
|
||||
func buildAltairBeaconBlockFromBlockData(blkData *blockData) *ethpb.BeaconBlockAltair {
|
||||
// Use zero hash as stub for state root to compute later.
|
||||
stateRoot := params.BeaconConfig().ZeroHash[:]
|
||||
|
||||
// No need for safe sub as req.Slot cannot be 0 if requesting Altair blocks. If 0, we will be throwing
|
||||
// an error in the first validity check of this endpoint.
|
||||
syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(blkData.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ðpb.BeaconBlockAltair{
|
||||
Slot: req.Slot,
|
||||
Slot: blkData.Slot,
|
||||
ParentRoot: blkData.ParentRoot,
|
||||
StateRoot: stateRoot,
|
||||
ProposerIndex: blkData.ProposerIdx,
|
||||
@@ -42,14 +28,24 @@ func (vs *Server) BuildAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRe
|
||||
Eth1Data: blkData.Eth1Data,
|
||||
Deposits: blkData.Deposits,
|
||||
Attestations: blkData.Attestations,
|
||||
RandaoReveal: req.RandaoReveal,
|
||||
RandaoReveal: blkData.RandaoReveal,
|
||||
ProposerSlashings: blkData.ProposerSlashings,
|
||||
AttesterSlashings: blkData.AttesterSlashings,
|
||||
VoluntaryExits: blkData.VoluntaryExits,
|
||||
Graffiti: blkData.Graffiti[:],
|
||||
SyncAggregate: syncAggregate,
|
||||
SyncAggregate: blkData.SyncAggregate,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (vs *Server) BuildAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.BuildAltairBeaconBlock")
|
||||
defer span.End()
|
||||
blkData, err := vs.buildPhase0BlockData(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not build block data: %v", err)
|
||||
}
|
||||
return buildAltairBeaconBlockFromBlockData(blkData), nil
|
||||
}
|
||||
|
||||
func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) {
|
||||
|
||||
@@ -80,7 +80,7 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon
|
||||
// filter separates attestation list into two groups: valid and invalid attestations.
|
||||
// The first group passes the all the required checks for attestation to be considered for proposing.
|
||||
// And attestations from the second group should be deleted.
|
||||
func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (proposerAtts, proposerAtts) {
|
||||
func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (proposerAtts, proposerAtts, error) {
|
||||
validAtts := make([]*ethpb.Attestation, 0, len(a))
|
||||
invalidAtts := make([]*ethpb.Attestation, 0, len(a))
|
||||
var attestationProcessor func(context.Context, state.BeaconState, *ethpb.Attestation) (state.BeaconState, error)
|
||||
@@ -88,7 +88,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
switch st.Version() {
|
||||
case version.Phase0:
|
||||
attestationProcessor = blocks.ProcessAttestationNoVerifySignature
|
||||
case version.Altair, version.Bellatrix:
|
||||
case version.Altair, version.Bellatrix, version.Capella:
|
||||
// Use a wrapper here, as go needs strong typing for the function signature.
|
||||
attestationProcessor = func(ctx context.Context, st state.BeaconState, attestation *ethpb.Attestation) (state.BeaconState, error) {
|
||||
totalBalance, err := helpers.TotalActiveBalance(st)
|
||||
@@ -99,7 +99,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
}
|
||||
default:
|
||||
// Exit early if there is an unknown state type.
|
||||
return validAtts, invalidAtts
|
||||
return validAtts, invalidAtts, errors.Errorf("unknown state type: %v", st.Version())
|
||||
}
|
||||
for _, att := range a {
|
||||
if _, err := attestationProcessor(ctx, st, att); err == nil {
|
||||
@@ -108,7 +108,7 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
}
|
||||
invalidAtts = append(invalidAtts, att)
|
||||
}
|
||||
return validAtts, invalidAtts
|
||||
return validAtts, invalidAtts, nil
|
||||
}
|
||||
|
||||
// sortByProfitability orders attestations by highest slot and by highest aggregation bit count.
|
||||
@@ -247,7 +247,10 @@ func (vs *Server) validateAndDeleteAttsInPool(ctx context.Context, st state.Beac
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.validateAndDeleteAttsInPool")
|
||||
defer span.End()
|
||||
|
||||
validAtts, invalidAtts := proposerAtts(atts).filter(ctx, st)
|
||||
validAtts, invalidAtts, err := proposerAtts(atts).filter(ctx, st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := vs.deleteAttsInPool(ctx, invalidAtts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition/interop"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
@@ -38,68 +39,124 @@ var builderGetPayloadMissCount = promauto.NewCounter(prometheus.CounterOpts{
|
||||
// block request. This value is known as `BUILDER_PROPOSAL_DELAY_TOLERANCE` in builder spec.
|
||||
const blockBuilderTimeout = 1 * time.Second
|
||||
|
||||
func (vs *Server) getBlockFromBuilder(ctx context.Context, altairBlk *ethpb.BeaconBlockAltair) (
|
||||
*ethpb.GenericBeaconBlock, error) {
|
||||
registered, err := vs.validatorRegistered(ctx, altairBlk.ProposerIndex)
|
||||
if registered && err == nil {
|
||||
builderReady, b, err := vs.GetAndBuildBlindBlock(ctx, altairBlk)
|
||||
if err != nil {
|
||||
// In the event of an error, the node should fall back to default execution engine for building block.
|
||||
builderGetPayloadMissCount.Inc()
|
||||
return nil, err
|
||||
} else if builderReady {
|
||||
return b, nil
|
||||
}
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.New("validator is not registered")
|
||||
}
|
||||
|
||||
func (vs *Server) getBellatrixBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) {
|
||||
altairBlk, err := vs.BuildAltairBeaconBlock(ctx, req)
|
||||
blkData, err := vs.buildPhase0BlockData(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !req.SkipMevBoost {
|
||||
registered, err := vs.validatorRegistered(ctx, altairBlk.ProposerIndex)
|
||||
if registered && err == nil {
|
||||
builderReady, b, err := vs.GetAndBuildBlindBlock(ctx, altairBlk)
|
||||
if err != nil {
|
||||
// In the event of an error, the node should fall back to default execution engine for building block.
|
||||
log.WithError(err).Error("Failed to build a block from external builder, falling " +
|
||||
"back to local execution client")
|
||||
builderGetPayloadMissCount.Inc()
|
||||
} else if builderReady {
|
||||
return b, nil
|
||||
}
|
||||
} else if err != nil {
|
||||
log.WithError(err).WithFields(logrus.Fields{
|
||||
"slot": req.Slot,
|
||||
"validatorIndex": altairBlk.ProposerIndex,
|
||||
}).Error("Could not determine validator has registered. Defaulting to local execution client")
|
||||
// If the validator was not registered then we computed already an execution payload
|
||||
if !req.SkipMevBoost && blkData.ExecutionPayload == nil && blkData.ExecutionPayloadV2 == nil {
|
||||
altairBlk := buildAltairBeaconBlockFromBlockData(blkData)
|
||||
b, err := vs.getBlockFromBuilder(ctx, altairBlk)
|
||||
if err == nil {
|
||||
return b, nil
|
||||
}
|
||||
log.WithError(err).Error("falling back to local execution")
|
||||
|
||||
head, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get head state %v", err)
|
||||
}
|
||||
|
||||
head, err = transition.ProcessSlotsUsingNextSlotCache(ctx, head, blkData.ParentRoot, req.Slot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not advance slots to calculate proposer index: %v", err)
|
||||
}
|
||||
|
||||
blkData.ExecutionPayload, err = vs.getExecutionPayload(ctx, req.Slot, blkData.ProposerIdx, bytesutil.ToBytes32(blkData.ParentRoot), head)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
}
|
||||
payload, err := vs.getExecutionPayload(ctx, req.Slot, altairBlk.ProposerIndex, bytesutil.ToBytes32(altairBlk.ParentRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blk := ðpb.BeaconBlockBellatrix{
|
||||
Slot: altairBlk.Slot,
|
||||
ProposerIndex: altairBlk.ProposerIndex,
|
||||
ParentRoot: altairBlk.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
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,
|
||||
ExecutionPayload: payload,
|
||||
},
|
||||
}
|
||||
// Compute state root with the newly constructed block.
|
||||
wsb, err := consensusblocks.NewSignedBeaconBlock(
|
||||
ðpb.SignedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var wsb interfaces.SignedBeaconBlock
|
||||
if slots.ToEpoch(req.Slot) < params.BeaconConfig().CapellaForkEpoch {
|
||||
blk := ðpb.BeaconBlockBellatrix{
|
||||
Slot: blkData.Slot,
|
||||
ProposerIndex: blkData.ProposerIdx,
|
||||
ParentRoot: blkData.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||
RandaoReveal: blkData.RandaoReveal,
|
||||
Eth1Data: blkData.Eth1Data,
|
||||
Graffiti: blkData.Graffiti[:],
|
||||
ProposerSlashings: blkData.ProposerSlashings,
|
||||
AttesterSlashings: blkData.AttesterSlashings,
|
||||
Attestations: blkData.Attestations,
|
||||
Deposits: blkData.Deposits,
|
||||
VoluntaryExits: blkData.VoluntaryExits,
|
||||
SyncAggregate: blkData.SyncAggregate,
|
||||
ExecutionPayload: blkData.ExecutionPayload,
|
||||
},
|
||||
}
|
||||
// Compute state root with the newly constructed block.
|
||||
wsb, err = consensusblocks.NewSignedBeaconBlock(
|
||||
ðpb.SignedBeaconBlockBellatrix{Block: blk, Signature: make([]byte, 96)},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
blk := ðpb.BeaconBlockCapella{
|
||||
Slot: blkData.Slot,
|
||||
ProposerIndex: blkData.ProposerIdx,
|
||||
ParentRoot: blkData.ParentRoot,
|
||||
StateRoot: params.BeaconConfig().ZeroHash[:],
|
||||
Body: ðpb.BeaconBlockBodyCapella{
|
||||
RandaoReveal: blkData.RandaoReveal,
|
||||
Eth1Data: blkData.Eth1Data,
|
||||
Graffiti: blkData.Graffiti[:],
|
||||
ProposerSlashings: blkData.ProposerSlashings,
|
||||
AttesterSlashings: blkData.AttesterSlashings,
|
||||
Attestations: blkData.Attestations,
|
||||
Deposits: blkData.Deposits,
|
||||
VoluntaryExits: blkData.VoluntaryExits,
|
||||
SyncAggregate: blkData.SyncAggregate,
|
||||
ExecutionPayload: blkData.ExecutionPayloadV2,
|
||||
BlsToExecutionChanges: blkData.BlsToExecutionChanges,
|
||||
},
|
||||
}
|
||||
// Compute state root with the newly constructed block.
|
||||
wsb, err = consensusblocks.NewSignedBeaconBlock(
|
||||
ðpb.SignedBeaconBlockCapella{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_Bellatrix{Bellatrix: blk}}, nil
|
||||
wsb.Block().SetStateRoot(stateRoot)
|
||||
pb, err := wsb.Block().Proto()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not unmarshal block")
|
||||
}
|
||||
if slots.ToEpoch(req.Slot) < params.BeaconConfig().CapellaForkEpoch {
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}}, nil
|
||||
}
|
||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}}, nil
|
||||
}
|
||||
|
||||
// This function retrieves the payload header given the slot number and the validator index.
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db/kv"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
@@ -38,9 +38,14 @@ var (
|
||||
})
|
||||
)
|
||||
|
||||
// This returns the execution payload of a given slot. The function has full awareness of pre and post merge.
|
||||
// This returns the execution payload of a given slot.
|
||||
// The function has full awareness of pre and post merge.
|
||||
// The payload is computed given the respected time of merge.
|
||||
func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx types.ValidatorIndex, headRoot [32]byte) (*enginev1.ExecutionPayload, error) {
|
||||
func (vs *Server) getExecutionPayload(ctx context.Context,
|
||||
slot types.Slot,
|
||||
vIdx types.ValidatorIndex,
|
||||
headRoot [32]byte,
|
||||
st state.BeaconState) (*enginev1.ExecutionPayload, error) {
|
||||
proposerID, payloadId, ok := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, headRoot)
|
||||
feeRecipient := params.BeaconConfig().DefaultFeeRecipient
|
||||
recipient, err := vs.BeaconDB.FeeRecipientByValidatorID(ctx, vIdx)
|
||||
@@ -70,7 +75,7 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
payload, err := vs.ExecutionEngineCaller.GetPayload(ctx, pid)
|
||||
switch {
|
||||
case err == nil:
|
||||
warnIfFeeRecipientDiffers(payload, feeRecipient)
|
||||
warnIfFeeRecipientDiffers(payload.FeeRecipient, feeRecipient)
|
||||
return payload, nil
|
||||
case errors.Is(err, context.DeadlineExceeded):
|
||||
default:
|
||||
@@ -78,15 +83,6 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
}
|
||||
}
|
||||
|
||||
st, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, err = transition.ProcessSlotsIfPossible(ctx, st, slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var parentHash []byte
|
||||
var hasTerminalBlock bool
|
||||
mergeComplete, err := blocks.IsMergeTransitionComplete(st)
|
||||
@@ -165,18 +161,129 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
warnIfFeeRecipientDiffers(payload, feeRecipient)
|
||||
warnIfFeeRecipientDiffers(payload.FeeRecipient, feeRecipient)
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// This returns the execution payload of a given slot after the Capella upgrade
|
||||
func (vs *Server) getExecutionPayloadV2(ctx context.Context,
|
||||
slot types.Slot,
|
||||
vIdx types.ValidatorIndex,
|
||||
headRoot [32]byte,
|
||||
st state.BeaconState) (*enginev1.ExecutionPayloadCapella, error) {
|
||||
proposerID, payloadId, ok := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(slot, headRoot)
|
||||
feeRecipient := params.BeaconConfig().DefaultFeeRecipient
|
||||
recipient, err := vs.BeaconDB.FeeRecipientByValidatorID(ctx, vIdx)
|
||||
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 feeRecipient.String() == params.BeaconConfig().EthBurnAddressHex {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"validatorIndex": vIdx,
|
||||
"burnAddress": params.BeaconConfig().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")
|
||||
}
|
||||
|
||||
if ok && proposerID == vIdx && payloadId != [8]byte{} { // Payload ID is cache hit. Return the cached payload ID.
|
||||
var pid [8]byte
|
||||
copy(pid[:], payloadId[:])
|
||||
payloadIDCacheHit.Inc()
|
||||
payload, err := vs.ExecutionEngineCaller.GetPayloadV2(ctx, pid)
|
||||
switch {
|
||||
case err == nil:
|
||||
warnIfFeeRecipientDiffers(payload.FeeRecipient, feeRecipient)
|
||||
return payload, nil
|
||||
case errors.Is(err, context.DeadlineExceeded):
|
||||
default:
|
||||
return nil, errors.Wrap(err, "could not get cached payload from execution client")
|
||||
}
|
||||
}
|
||||
payloadIDCacheMiss.Inc()
|
||||
|
||||
header, err := st.LatestExecutionPayloadHeader()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get latest execution payload header")
|
||||
}
|
||||
parentHash := header.BlockHash()
|
||||
|
||||
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedBlockHash := params.BeaconConfig().ZeroHash[:]
|
||||
finalizedRoot := bytesutil.ToBytes32(st.FinalizedCheckpoint().Root)
|
||||
if finalizedRoot != [32]byte{} { // finalized root could be zeros before the first finalized block.
|
||||
finalizedBlock, err := vs.BeaconDB.Block(ctx, bytesutil.ToBytes32(st.FinalizedCheckpoint().Root))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := consensusblocks.BeaconBlockIsNil(finalizedBlock); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch finalizedBlock.Version() {
|
||||
case version.Phase0, version.Altair: // Blocks before Bellatrix don't have execution payloads. Use zeros as the hash.
|
||||
default:
|
||||
finalizedPayload, err := finalizedBlock.Block().Body().Execution()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalizedBlockHash = finalizedPayload.BlockHash()
|
||||
}
|
||||
}
|
||||
|
||||
f := &enginev1.ForkchoiceState{
|
||||
HeadBlockHash: parentHash,
|
||||
SafeBlockHash: parentHash,
|
||||
FinalizedBlockHash: finalizedBlockHash,
|
||||
}
|
||||
|
||||
t, err := slots.ToTime(st.GenesisTime(), slot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
withdrawals, err := st.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get expected withdrawals")
|
||||
}
|
||||
|
||||
p := &enginev1.PayloadAttributesV2{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
PrevRandao: random,
|
||||
SuggestedFeeRecipient: feeRecipient.Bytes(),
|
||||
Withdrawals: withdrawals,
|
||||
}
|
||||
payloadID, _, err := vs.ExecutionEngineCaller.ForkchoiceUpdatedV2(ctx, f, p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not prepare payload")
|
||||
}
|
||||
if payloadID == nil {
|
||||
return nil, fmt.Errorf("nil payload with block hash: %#x", parentHash)
|
||||
}
|
||||
payload, err := vs.ExecutionEngineCaller.GetPayloadV2(ctx, *payloadID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
warnIfFeeRecipientDiffers(payload.FeeRecipient, feeRecipient)
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// warnIfFeeRecipientDiffers logs a warning if the fee recipient in the included payload does not
|
||||
// match the requested one.
|
||||
func warnIfFeeRecipientDiffers(payload *enginev1.ExecutionPayload, feeRecipient common.Address) {
|
||||
func warnIfFeeRecipientDiffers(payloadRecipient []byte, feeRecipient common.Address) {
|
||||
// Warn if the fee recipient is not the value we expect.
|
||||
if payload != nil && !bytes.Equal(payload.FeeRecipient, feeRecipient[:]) {
|
||||
if !bytes.Equal(payloadRecipient, feeRecipient[:]) {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"wantedFeeRecipient": fmt.Sprintf("%#x", feeRecipient),
|
||||
"received": fmt.Sprintf("%#x", payload.FeeRecipient),
|
||||
"received": fmt.Sprintf("%#x", payloadRecipient),
|
||||
}).Warn("Fee recipient address from execution client is not what was expected. " +
|
||||
"It is possible someone has compromised your client to try and take your transaction fees")
|
||||
}
|
||||
|
||||
@@ -14,21 +14,29 @@ import (
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// blockData required to create a beacon block.
|
||||
type blockData struct {
|
||||
ParentRoot []byte
|
||||
Graffiti [32]byte
|
||||
ProposerIdx types.ValidatorIndex
|
||||
Eth1Data *ethpb.Eth1Data
|
||||
Deposits []*ethpb.Deposit
|
||||
Attestations []*ethpb.Attestation
|
||||
ProposerSlashings []*ethpb.ProposerSlashing
|
||||
AttesterSlashings []*ethpb.AttesterSlashing
|
||||
VoluntaryExits []*ethpb.SignedVoluntaryExit
|
||||
Slot types.Slot
|
||||
ParentRoot []byte
|
||||
Graffiti [32]byte
|
||||
ProposerIdx types.ValidatorIndex
|
||||
Eth1Data *ethpb.Eth1Data
|
||||
Deposits []*ethpb.Deposit
|
||||
Attestations []*ethpb.Attestation
|
||||
RandaoReveal []byte
|
||||
ProposerSlashings []*ethpb.ProposerSlashing
|
||||
AttesterSlashings []*ethpb.AttesterSlashing
|
||||
VoluntaryExits []*ethpb.SignedVoluntaryExit
|
||||
SyncAggregate *ethpb.SyncAggregate
|
||||
ExecutionPayload *enginev1.ExecutionPayload
|
||||
ExecutionPayloadV2 *enginev1.ExecutionPayloadCapella
|
||||
BlsToExecutionChanges []*ethpb.SignedBLSToExecutionChange
|
||||
}
|
||||
|
||||
func (vs *Server) getPhase0BeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlock, error) {
|
||||
@@ -43,7 +51,7 @@ func (vs *Server) getPhase0BeaconBlock(ctx context.Context, req *ethpb.BlockRequ
|
||||
stateRoot := params.BeaconConfig().ZeroHash[:]
|
||||
|
||||
blk := ðpb.BeaconBlock{
|
||||
Slot: req.Slot,
|
||||
Slot: blkData.Slot,
|
||||
ParentRoot: blkData.ParentRoot,
|
||||
StateRoot: stateRoot,
|
||||
ProposerIndex: blkData.ProposerIdx,
|
||||
@@ -51,7 +59,7 @@ func (vs *Server) getPhase0BeaconBlock(ctx context.Context, req *ethpb.BlockRequ
|
||||
Eth1Data: blkData.Eth1Data,
|
||||
Deposits: blkData.Deposits,
|
||||
Attestations: blkData.Attestations,
|
||||
RandaoReveal: req.RandaoReveal,
|
||||
RandaoReveal: blkData.RandaoReveal,
|
||||
ProposerSlashings: blkData.ProposerSlashings,
|
||||
AttesterSlashings: blkData.AttesterSlashings,
|
||||
VoluntaryExits: blkData.VoluntaryExits,
|
||||
@@ -156,15 +164,66 @@ func (vs *Server) buildPhase0BlockData(ctx context.Context, req *ethpb.BlockRequ
|
||||
validExits = append(validExits, exit)
|
||||
}
|
||||
|
||||
return &blockData{
|
||||
blk := &blockData{
|
||||
Slot: req.Slot,
|
||||
ParentRoot: parentRoot,
|
||||
Graffiti: graffiti,
|
||||
ProposerIdx: idx,
|
||||
Eth1Data: eth1Data,
|
||||
Deposits: deposits,
|
||||
Attestations: atts,
|
||||
RandaoReveal: req.RandaoReveal,
|
||||
ProposerSlashings: validProposerSlashings,
|
||||
AttesterSlashings: validAttSlashings,
|
||||
VoluntaryExits: validExits,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().AltairForkEpoch {
|
||||
syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(parentRoot))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute the sync aggregate")
|
||||
}
|
||||
|
||||
blk.SyncAggregate = syncAggregate
|
||||
}
|
||||
|
||||
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().BellatrixForkEpoch {
|
||||
// We request the execution payload only if the validator is not registered
|
||||
// with a relayer
|
||||
registered, err := vs.validatorRegistered(ctx, idx)
|
||||
if !registered || err != nil {
|
||||
if slots.ToEpoch(req.Slot) >= params.BeaconConfig().CapellaForkEpoch {
|
||||
executionPayloadV2, err := vs.getExecutionPayloadV2(
|
||||
ctx,
|
||||
req.Slot,
|
||||
idx,
|
||||
bytesutil.ToBytes32(parentRoot),
|
||||
head,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
blk.ExecutionPayloadV2 = executionPayloadV2
|
||||
changes, err := vs.BLSChangesPool.BLSToExecChangesForInclusion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not pack BLSToExecutionChanges")
|
||||
}
|
||||
blk.BlsToExecutionChanges = changes
|
||||
} else {
|
||||
executionPayload, err := vs.getExecutionPayload(
|
||||
ctx,
|
||||
req.Slot,
|
||||
idx,
|
||||
bytesutil.ToBytes32(parentRoot),
|
||||
head,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get execution payload")
|
||||
}
|
||||
blk.ExecutionPayload = executionPayload
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blk, nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/execution"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits"
|
||||
@@ -62,6 +63,7 @@ type Server struct {
|
||||
SlashingsPool slashings.PoolManager
|
||||
ExitPool voluntaryexits.PoolManager
|
||||
SyncCommitteePool synccommittee.Pool
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
BlockReceiver blockchain.BlockReceiver
|
||||
MockEth1Votes bool
|
||||
Eth1BlockFetcher execution.POWBlockFetcher
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/execution"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/blstoexec"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/slashings"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/synccommittee"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/operations/voluntaryexits"
|
||||
@@ -99,6 +100,7 @@ type Config struct {
|
||||
SlashingsPool slashings.PoolManager
|
||||
SlashingChecker slasherservice.SlashingChecker
|
||||
SyncCommitteeObjectPool synccommittee.Pool
|
||||
BLSChangesPool blstoexec.PoolManager
|
||||
SyncService chainSync.Checker
|
||||
Broadcaster p2p.Broadcaster
|
||||
PeersFetcher p2p.PeersProvider
|
||||
@@ -216,6 +218,7 @@ func (s *Service) Start() {
|
||||
SlashingsPool: s.cfg.SlashingsPool,
|
||||
StateGen: s.cfg.StateGen,
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
BLSChangesPool: s.cfg.BLSChangesPool,
|
||||
ReplayerBuilder: ch,
|
||||
ExecutionEngineCaller: s.cfg.ExecutionEngineCaller,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
@@ -240,6 +243,7 @@ func (s *Service) Start() {
|
||||
ReplayerBuilder: ch,
|
||||
},
|
||||
SyncCommitteePool: s.cfg.SyncCommitteeObjectPool,
|
||||
BLSChangesPool: s.cfg.BLSChangesPool,
|
||||
ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
@@ -48,7 +49,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, params.BeaconConfig().MaxWithdrawalsPerPayload)
|
||||
withdrawals := make([]*enginev1.Withdrawal, 0, fieldparams.MaxWithdrawalsPerPayload)
|
||||
validatorIndex := b.nextWithdrawalValidatorIndex
|
||||
withdrawalIndex := b.nextWithdrawalIndex
|
||||
epoch := slots.ToEpoch(b.slot)
|
||||
@@ -72,7 +73,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, error) {
|
||||
})
|
||||
withdrawalIndex++
|
||||
}
|
||||
if uint64(len(withdrawals)) == params.BeaconConfig().MaxWithdrawalsPerPayload {
|
||||
if uint64(len(withdrawals)) == fieldparams.MaxWithdrawalsPerPayload {
|
||||
break
|
||||
}
|
||||
validatorIndex += 1
|
||||
|
||||
@@ -165,6 +165,7 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c
|
||||
disableBroadcastSlashingFlag,
|
||||
enableSlasherFlag,
|
||||
enableHistoricalSpaceRepresentation,
|
||||
disableStakinContractCheck,
|
||||
disablePullTips,
|
||||
disableVecHTR,
|
||||
disableForkChoiceDoublyLinkedTree,
|
||||
|
||||
@@ -26,6 +26,4 @@ const (
|
||||
SyncCommitteeAggregationBytesLength = 16 // SyncCommitteeAggregationBytesLength defines the length of sync committee aggregate bytes.
|
||||
SyncAggregateSyncCommitteeBytesLength = 64 // SyncAggregateSyncCommitteeBytesLength defines the length of sync committee bytes in a sync aggregate.
|
||||
MaxWithdrawalsPerPayload = 16 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload.
|
||||
WithdrawalQueueLimit = 1099511627776 // WithdrawalQueueLimit defines the maximum number of withdrawals queued in the state.
|
||||
ExecutionAddressLength = 20 // ExecutionAddressLength defines the length of an execution layer address.
|
||||
)
|
||||
|
||||
@@ -25,6 +25,5 @@ const (
|
||||
SlotsPerEpoch = 8 // SlotsPerEpoch defines the number of slots per epoch.
|
||||
SyncCommitteeAggregationBytesLength = 1 // SyncCommitteeAggregationBytesLength defines the sync committee aggregate bytes.
|
||||
SyncAggregateSyncCommitteeBytesLength = 4 // SyncAggregateSyncCommitteeBytesLength defines the length of sync committee bytes in a sync aggregate.
|
||||
MaxWithdrawalsPerPayload = 16 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload.
|
||||
WithdrawalQueueLimit = 1099511627776 // WithdrawalQueueLimit defines the maximum number of withdrawals queued in the state.
|
||||
MaxWithdrawalsPerPayload = 4 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload.
|
||||
)
|
||||
|
||||
@@ -226,6 +226,8 @@ func configForkSchedule(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt
|
||||
fvs[bytesutil.ToBytes4(b.AltairForkVersion)] = b.AltairForkEpoch
|
||||
// Set Bellatrix fork data.
|
||||
fvs[bytesutil.ToBytes4(b.BellatrixForkVersion)] = b.BellatrixForkEpoch
|
||||
// Set Capella fork data.
|
||||
fvs[bytesutil.ToBytes4(b.CapellaForkVersion)] = b.CapellaForkEpoch
|
||||
return fvs
|
||||
}
|
||||
|
||||
@@ -237,5 +239,7 @@ func configForkNames(b *BeaconChainConfig) map[[fieldparams.VersionLength]byte]s
|
||||
fvn[bytesutil.ToBytes4(b.AltairForkVersion)] = "altair"
|
||||
// Set Bellatrix fork data.
|
||||
fvn[bytesutil.ToBytes4(b.BellatrixForkVersion)] = "bellatrix"
|
||||
// Set Capella fork data.
|
||||
fvn[bytesutil.ToBytes4(b.CapellaForkVersion)] = "capella"
|
||||
return fvn
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ func InteropConfig() *BeaconChainConfig {
|
||||
c.GenesisForkVersion = []byte{0, 0, 0, 235}
|
||||
c.AltairForkVersion = []byte{1, 0, 0, 235}
|
||||
c.BellatrixForkVersion = []byte{2, 0, 0, 235}
|
||||
c.ShardingForkVersion = []byte{3, 0, 0, 235}
|
||||
c.CapellaForkVersion = []byte{3, 0, 0, 235}
|
||||
c.ShardingForkVersion = []byte{4, 0, 0, 235}
|
||||
|
||||
c.InitializeForkSchedule()
|
||||
return c
|
||||
|
||||
@@ -42,7 +42,8 @@ func E2ETestConfig() *BeaconChainConfig {
|
||||
e2eConfig.GenesisForkVersion = []byte{0, 0, 0, 253}
|
||||
e2eConfig.AltairForkVersion = []byte{1, 0, 0, 253}
|
||||
e2eConfig.BellatrixForkVersion = []byte{2, 0, 0, 253}
|
||||
e2eConfig.ShardingForkVersion = []byte{3, 0, 0, 253}
|
||||
e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 253}
|
||||
e2eConfig.ShardingForkVersion = []byte{4, 0, 0, 253}
|
||||
|
||||
e2eConfig.InitializeForkSchedule()
|
||||
return e2eConfig
|
||||
@@ -79,7 +80,8 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
|
||||
e2eConfig.GenesisForkVersion = []byte{0, 0, 0, 254}
|
||||
e2eConfig.AltairForkVersion = []byte{1, 0, 0, 254}
|
||||
e2eConfig.BellatrixForkVersion = []byte{2, 0, 0, 254}
|
||||
e2eConfig.ShardingForkVersion = []byte{3, 0, 0, 254}
|
||||
e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 254}
|
||||
e2eConfig.ShardingForkVersion = []byte{4, 0, 0, 254}
|
||||
|
||||
e2eConfig.InitializeForkSchedule()
|
||||
return e2eConfig
|
||||
|
||||
@@ -32,6 +32,7 @@ func RopstenConfig() *BeaconChainConfig {
|
||||
cfg.AltairForkVersion = []byte{0x80, 0x00, 0x00, 0x70}
|
||||
cfg.BellatrixForkEpoch = 750
|
||||
cfg.BellatrixForkVersion = []byte{0x80, 0x00, 0x00, 0x71}
|
||||
cfg.CapellaForkVersion = []byte{0x80, 0x00, 0x00, 0x72}
|
||||
cfg.TerminalTotalDifficulty = "50000000000000000"
|
||||
cfg.DepositContractAddress = "0x6f22fFbC56eFF051aECF839396DD1eD9aD6BBA9D"
|
||||
cfg.InitializeForkSchedule()
|
||||
|
||||
@@ -647,10 +647,6 @@ func PayloadToHeaderCapella(payload interfaces.ExecutionData) (*enginev1.Executi
|
||||
// IsEmptyExecutionData checks if an execution data is empty underneath. If a single field has
|
||||
// a non-zero value, this function will return false.
|
||||
func IsEmptyExecutionData(data interfaces.ExecutionData) (bool, error) {
|
||||
_, ok := data.Proto().(*enginev1.ExecutionPayloadCapella)
|
||||
if ok {
|
||||
return false, nil
|
||||
}
|
||||
if !bytes.Equal(data.ParentHash(), make([]byte, fieldparams.RootLength)) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -473,6 +473,13 @@ func (b *BeaconBlock) StateRoot() [field_params.RootLength]byte {
|
||||
return b.stateRoot
|
||||
}
|
||||
|
||||
// SetStateRoot sets the state root of the underlying beacon block
|
||||
// This function is not thread safe, it is only used during block
|
||||
// proposal to set the state root of a new block
|
||||
func (b *BeaconBlock) SetStateRoot(root []byte) {
|
||||
copy(b.stateRoot[:], root)
|
||||
}
|
||||
|
||||
// Body returns the underlying block body.
|
||||
func (b *BeaconBlock) Body() interfaces.BeaconBlockBody {
|
||||
return b.body
|
||||
|
||||
@@ -40,6 +40,7 @@ type BeaconBlock interface {
|
||||
ProposerIndex() types.ValidatorIndex
|
||||
ParentRoot() [field_params.RootLength]byte
|
||||
StateRoot() [field_params.RootLength]byte
|
||||
SetStateRoot([]byte)
|
||||
Body() BeaconBlockBody
|
||||
IsNil() bool
|
||||
IsBlinded() bool
|
||||
|
||||
@@ -99,6 +99,15 @@ func ToBytes4(x []byte) [4]byte {
|
||||
return y
|
||||
}
|
||||
|
||||
// ToBytes20 is a convenience method for converting a byte slice to a fix
|
||||
// sized 20 byte array. This method will truncate the input if it is larger
|
||||
// than 20 bytes.
|
||||
func ToBytes20(x []byte) [20]byte {
|
||||
var y [20]byte
|
||||
copy(y[:], x)
|
||||
return y
|
||||
}
|
||||
|
||||
// ToBytes32 is a convenience method for converting a byte slice to a fix
|
||||
// sized 32 byte array. This method will truncate the input if it is larger
|
||||
// than 32 bytes.
|
||||
|
||||
@@ -41,7 +41,6 @@ go_test(
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
gethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/pkg/errors"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
)
|
||||
|
||||
@@ -109,6 +110,58 @@ func (b *PayloadIDBytes) UnmarshalJSON(enc []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type withdrawalJSON struct {
|
||||
Index *hexutil.Uint64 `json:"index"`
|
||||
Validator *hexutil.Uint64 `json:"validatorIndex"`
|
||||
Address *common.Address `json:"address"`
|
||||
Amount string `json:"amount"`
|
||||
}
|
||||
|
||||
func (w *Withdrawal) MarshalJSON() ([]byte, error) {
|
||||
index := hexutil.Uint64(w.WithdrawalIndex)
|
||||
validatorIndex := hexutil.Uint64(w.ValidatorIndex)
|
||||
address := common.BytesToAddress(w.ExecutionAddress)
|
||||
wei := new(big.Int).SetUint64(1000000000)
|
||||
amountWei := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), wei)
|
||||
return json.Marshal(withdrawalJSON{
|
||||
Index: &index,
|
||||
Validator: &validatorIndex,
|
||||
Address: &address,
|
||||
Amount: hexutil.EncodeBig(amountWei),
|
||||
})
|
||||
}
|
||||
|
||||
func (w *Withdrawal) UnmarshalJSON(enc []byte) error {
|
||||
dec := withdrawalJSON{}
|
||||
if err := json.Unmarshal(enc, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
if dec.Index == nil {
|
||||
return errors.New("missing withdrawal index")
|
||||
}
|
||||
if dec.Validator == nil {
|
||||
return errors.New("missing validator index")
|
||||
}
|
||||
if dec.Address == nil {
|
||||
return errors.New("missing execution address")
|
||||
}
|
||||
*w = Withdrawal{}
|
||||
w.WithdrawalIndex = uint64(*dec.Index)
|
||||
w.ValidatorIndex = types.ValidatorIndex(*dec.Validator)
|
||||
w.ExecutionAddress = dec.Address.Bytes()
|
||||
wei := new(big.Int).SetUint64(1000000000)
|
||||
amountWei, err := hexutil.DecodeBig(dec.Amount)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amount := new(big.Int).Div(amountWei, wei)
|
||||
if !amount.IsUint64() {
|
||||
return errors.New("withdrawal amount overflow")
|
||||
}
|
||||
w.Amount = amount.Uint64()
|
||||
return nil
|
||||
}
|
||||
|
||||
type executionPayloadJSON struct {
|
||||
ParentHash *common.Hash `json:"parentHash"`
|
||||
FeeRecipient *common.Address `json:"feeRecipient"`
|
||||
@@ -126,6 +179,24 @@ type executionPayloadJSON struct {
|
||||
Transactions []hexutil.Bytes `json:"transactions"`
|
||||
}
|
||||
|
||||
type executionPayloadCapellaJSON struct {
|
||||
ParentHash *common.Hash `json:"parentHash"`
|
||||
FeeRecipient *common.Address `json:"feeRecipient"`
|
||||
StateRoot *common.Hash `json:"stateRoot"`
|
||||
ReceiptsRoot *common.Hash `json:"receiptsRoot"`
|
||||
LogsBloom *hexutil.Bytes `json:"logsBloom"`
|
||||
PrevRandao *common.Hash `json:"prevRandao"`
|
||||
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
|
||||
GasLimit *hexutil.Uint64 `json:"gasLimit"`
|
||||
GasUsed *hexutil.Uint64 `json:"gasUsed"`
|
||||
Timestamp *hexutil.Uint64 `json:"timestamp"`
|
||||
ExtraData hexutil.Bytes `json:"extraData"`
|
||||
BaseFeePerGas string `json:"baseFeePerGas"`
|
||||
BlockHash *common.Hash `json:"blockHash"`
|
||||
Transactions []hexutil.Bytes `json:"transactions"`
|
||||
Withdrawals []*Withdrawal `json:"withdrawals"`
|
||||
}
|
||||
|
||||
// MarshalJSON --
|
||||
func (e *ExecutionPayload) MarshalJSON() ([]byte, error) {
|
||||
transactions := make([]hexutil.Bytes, len(e.Transactions))
|
||||
@@ -163,6 +234,47 @@ func (e *ExecutionPayload) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// MarshalJSON --
|
||||
func (e *ExecutionPayloadCapella) MarshalJSON() ([]byte, error) {
|
||||
transactions := make([]hexutil.Bytes, len(e.Transactions))
|
||||
for i, tx := range e.Transactions {
|
||||
transactions[i] = tx
|
||||
}
|
||||
baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas))
|
||||
baseFeeHex := hexutil.EncodeBig(baseFee)
|
||||
pHash := common.BytesToHash(e.ParentHash)
|
||||
sRoot := common.BytesToHash(e.StateRoot)
|
||||
recRoot := common.BytesToHash(e.ReceiptsRoot)
|
||||
prevRan := common.BytesToHash(e.PrevRandao)
|
||||
bHash := common.BytesToHash(e.BlockHash)
|
||||
blockNum := hexutil.Uint64(e.BlockNumber)
|
||||
gasLimit := hexutil.Uint64(e.GasLimit)
|
||||
gasUsed := hexutil.Uint64(e.GasUsed)
|
||||
timeStamp := hexutil.Uint64(e.Timestamp)
|
||||
recipient := common.BytesToAddress(e.FeeRecipient)
|
||||
logsBloom := hexutil.Bytes(e.LogsBloom)
|
||||
if e.Withdrawals == nil {
|
||||
e.Withdrawals = make([]*Withdrawal, 0)
|
||||
}
|
||||
return json.Marshal(executionPayloadCapellaJSON{
|
||||
ParentHash: &pHash,
|
||||
FeeRecipient: &recipient,
|
||||
StateRoot: &sRoot,
|
||||
ReceiptsRoot: &recRoot,
|
||||
LogsBloom: &logsBloom,
|
||||
PrevRandao: &prevRan,
|
||||
BlockNumber: &blockNum,
|
||||
GasLimit: &gasLimit,
|
||||
GasUsed: &gasUsed,
|
||||
Timestamp: &timeStamp,
|
||||
ExtraData: e.ExtraData,
|
||||
BaseFeePerGas: baseFeeHex,
|
||||
BlockHash: &bHash,
|
||||
Transactions: transactions,
|
||||
Withdrawals: e.Withdrawals,
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON --
|
||||
func (e *ExecutionPayload) UnmarshalJSON(enc []byte) error {
|
||||
dec := executionPayloadJSON{}
|
||||
@@ -236,12 +348,96 @@ func (e *ExecutionPayload) UnmarshalJSON(enc []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON --
|
||||
func (e *ExecutionPayloadCapella) UnmarshalJSON(enc []byte) error {
|
||||
dec := executionPayloadCapellaJSON{}
|
||||
if err := json.Unmarshal(enc, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dec.ParentHash == nil {
|
||||
return errors.New("missing required field 'parentHash' for ExecutionPayload")
|
||||
}
|
||||
if dec.FeeRecipient == nil {
|
||||
return errors.New("missing required field 'feeRecipient' for ExecutionPayload")
|
||||
}
|
||||
if dec.StateRoot == nil {
|
||||
return errors.New("missing required field 'stateRoot' for ExecutionPayload")
|
||||
}
|
||||
if dec.ReceiptsRoot == nil {
|
||||
return errors.New("missing required field 'receiptsRoot' for ExecutableDataV1")
|
||||
}
|
||||
|
||||
if dec.LogsBloom == nil {
|
||||
return errors.New("missing required field 'logsBloom' for ExecutionPayload")
|
||||
}
|
||||
if dec.PrevRandao == nil {
|
||||
return errors.New("missing required field 'prevRandao' for ExecutionPayload")
|
||||
}
|
||||
if dec.ExtraData == nil {
|
||||
return errors.New("missing required field 'extraData' for ExecutionPayload")
|
||||
}
|
||||
if dec.BlockHash == nil {
|
||||
return errors.New("missing required field 'blockHash' for ExecutionPayload")
|
||||
}
|
||||
if dec.Transactions == nil {
|
||||
return errors.New("missing required field 'transactions' for ExecutionPayload")
|
||||
}
|
||||
if dec.BlockNumber == nil {
|
||||
return errors.New("missing required field 'blockNumber' for ExecutionPayload")
|
||||
}
|
||||
if dec.Timestamp == nil {
|
||||
return errors.New("missing required field 'timestamp' for ExecutionPayload")
|
||||
}
|
||||
if dec.GasUsed == nil {
|
||||
return errors.New("missing required field 'gasUsed' for ExecutionPayload")
|
||||
}
|
||||
if dec.GasLimit == nil {
|
||||
return errors.New("missing required field 'gasLimit' for ExecutionPayload")
|
||||
}
|
||||
*e = ExecutionPayloadCapella{}
|
||||
e.ParentHash = dec.ParentHash.Bytes()
|
||||
e.FeeRecipient = dec.FeeRecipient.Bytes()
|
||||
e.StateRoot = dec.StateRoot.Bytes()
|
||||
e.ReceiptsRoot = dec.ReceiptsRoot.Bytes()
|
||||
e.LogsBloom = *dec.LogsBloom
|
||||
e.PrevRandao = dec.PrevRandao.Bytes()
|
||||
e.BlockNumber = uint64(*dec.BlockNumber)
|
||||
e.GasLimit = uint64(*dec.GasLimit)
|
||||
e.GasUsed = uint64(*dec.GasUsed)
|
||||
e.Timestamp = uint64(*dec.Timestamp)
|
||||
e.ExtraData = dec.ExtraData
|
||||
baseFee, err := hexutil.DecodeBig(dec.BaseFeePerGas)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
|
||||
e.BlockHash = dec.BlockHash.Bytes()
|
||||
transactions := make([][]byte, len(dec.Transactions))
|
||||
for i, tx := range dec.Transactions {
|
||||
transactions[i] = tx
|
||||
}
|
||||
e.Transactions = transactions
|
||||
if dec.Withdrawals == nil {
|
||||
dec.Withdrawals = make([]*Withdrawal, 0)
|
||||
}
|
||||
e.Withdrawals = dec.Withdrawals
|
||||
return nil
|
||||
}
|
||||
|
||||
type payloadAttributesJSON struct {
|
||||
Timestamp hexutil.Uint64 `json:"timestamp"`
|
||||
PrevRandao hexutil.Bytes `json:"prevRandao"`
|
||||
SuggestedFeeRecipient hexutil.Bytes `json:"suggestedFeeRecipient"`
|
||||
}
|
||||
|
||||
type payloadAttributesV2JSON struct {
|
||||
Timestamp hexutil.Uint64 `json:"timestamp"`
|
||||
PrevRandao hexutil.Bytes `json:"prevRandao"`
|
||||
SuggestedFeeRecipient hexutil.Bytes `json:"suggestedFeeRecipient"`
|
||||
Withdrawals []*Withdrawal `json:"withdrawals"`
|
||||
}
|
||||
|
||||
// MarshalJSON --
|
||||
func (p *PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(payloadAttributesJSON{
|
||||
@@ -251,6 +447,16 @@ func (p *PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// MarshalJSON --
|
||||
func (p *PayloadAttributesV2) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(payloadAttributesV2JSON{
|
||||
Timestamp: hexutil.Uint64(p.Timestamp),
|
||||
PrevRandao: p.PrevRandao,
|
||||
SuggestedFeeRecipient: p.SuggestedFeeRecipient,
|
||||
Withdrawals: p.Withdrawals,
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON --
|
||||
func (p *PayloadAttributes) UnmarshalJSON(enc []byte) error {
|
||||
dec := payloadAttributesJSON{}
|
||||
@@ -264,6 +470,19 @@ func (p *PayloadAttributes) UnmarshalJSON(enc []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PayloadAttributesV2) UnmarshalJSON(enc []byte) error {
|
||||
dec := payloadAttributesV2JSON{}
|
||||
if err := json.Unmarshal(enc, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
*p = PayloadAttributesV2{}
|
||||
p.Timestamp = uint64(dec.Timestamp)
|
||||
p.PrevRandao = dec.PrevRandao
|
||||
p.SuggestedFeeRecipient = dec.SuggestedFeeRecipient
|
||||
p.Withdrawals = dec.Withdrawals
|
||||
return nil
|
||||
}
|
||||
|
||||
type payloadStatusJSON struct {
|
||||
LatestValidHash *common.Hash `json:"latestValidHash"`
|
||||
Status string `json:"status"`
|
||||
|
||||
@@ -193,5 +193,5 @@ func createDepositData(privKey bls.SecretKey, pubKey bls.PublicKey) (*ethpb.Depo
|
||||
// where withdrawal_credentials is of type bytes32.
|
||||
func withdrawalCredentialsHash(pubKey []byte) []byte {
|
||||
h := hash.Hash(pubKey)
|
||||
return append([]byte{blsWithdrawalPrefixByte}, h[1:]...)[:32]
|
||||
return append([]byte{1}, h[1:]...)[:32]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"effective_balance_updates_test.go",
|
||||
"eth1_data_reset_test.go",
|
||||
"historical_roots_update_test.go",
|
||||
"inactivity_updates_test.go",
|
||||
"justification_and_finalization_test.go",
|
||||
"participation_flag_updates_test.go",
|
||||
"randao_mixes_reset_test.go",
|
||||
"registry_updates_test.go",
|
||||
"rewards_and_penalties_test.go",
|
||||
"slashings_reset_test.go",
|
||||
"slashings_test.go",
|
||||
],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
shard_count = 4,
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/epoch_processing:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_EffectiveBalanceUpdates(t *testing.T) {
|
||||
epoch_processing.RunEffectiveBalanceUpdatesTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_Eth1DataReset(t *testing.T) {
|
||||
epoch_processing.RunEth1DataResetTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_HistoricalRootsUpdate(t *testing.T) {
|
||||
epoch_processing.RunHistoricalRootsUpdateTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_InactivityUpdates(t *testing.T) {
|
||||
epoch_processing.RunInactivityUpdatesTest(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_JustificationAndFinalization(t *testing.T) {
|
||||
epoch_processing.RunJustificationAndFinalizationTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_ParticipationFlag(t *testing.T) {
|
||||
epoch_processing.RunParticipationFlagUpdatesTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_RandaoMixesReset(t *testing.T) {
|
||||
epoch_processing.RunRandaoMixesResetTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_ResetRegistryUpdates(t *testing.T) {
|
||||
epoch_processing.RunRegistryUpdatesTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_RewardsAndPenalties(t *testing.T) {
|
||||
epoch_processing.RunRewardsAndPenaltiesTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_SlashingsReset(t *testing.T) {
|
||||
epoch_processing.RunSlashingsResetTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_EpochProcessing_Slashings(t *testing.T) {
|
||||
epoch_processing.RunSlashingsTests(t, "mainnet")
|
||||
}
|
||||
14
testing/spectest/mainnet/capella/finality/BUILD.bazel
Normal file
14
testing/spectest/mainnet/capella/finality/BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "medium",
|
||||
timeout = "short",
|
||||
srcs = ["finality_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
shard_count = 4,
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/finality:go_default_library"],
|
||||
)
|
||||
11
testing/spectest/mainnet/capella/finality/finality_test.go
Normal file
11
testing/spectest/mainnet/capella/finality/finality_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package finality
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/finality"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Finality(t *testing.T) {
|
||||
finality.RunFinalityTest(t, "mainnet")
|
||||
}
|
||||
13
testing/spectest/mainnet/capella/fork_helper/BUILD.bazel
Normal file
13
testing/spectest/mainnet/capella/fork_helper/BUILD.bazel
Normal file
@@ -0,0 +1,13 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["upgrade_to_capella_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
shard_count = 4,
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/fork:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package fork_helper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/fork"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_UpgradeToCapella(t *testing.T) {
|
||||
fork.RunUpgradeToCapella(t, "mainnet")
|
||||
}
|
||||
12
testing/spectest/mainnet/capella/fork_transition/BUILD.bazel
Normal file
12
testing/spectest/mainnet/capella/fork_transition/BUILD.bazel
Normal file
@@ -0,0 +1,12 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["transition_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/fork:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package fork_transition
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/fork"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Transition(t *testing.T) {
|
||||
fork.RunForkTransitionTest(t, "mainnet")
|
||||
}
|
||||
17
testing/spectest/mainnet/capella/forkchoice/BUILD.bazel
Normal file
17
testing/spectest/mainnet/capella/forkchoice/BUILD.bazel
Normal file
@@ -0,0 +1,17 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "enormous",
|
||||
timeout = "short",
|
||||
srcs = ["forkchoice_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
tags = ["spectest"],
|
||||
deps = [
|
||||
"//config/features:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/spectest/shared/common/forkchoice:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/config/features"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/common/forkchoice"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Forkchoice(t *testing.T) {
|
||||
resetCfg := features.InitWithReset(&features.Flags{
|
||||
EnableDefensivePull: false,
|
||||
DisablePullTips: true,
|
||||
})
|
||||
defer resetCfg()
|
||||
forkchoice.Run(t, "mainnet", version.Capella)
|
||||
}
|
||||
21
testing/spectest/mainnet/capella/operations/BUILD.bazel
Normal file
21
testing/spectest/mainnet/capella/operations/BUILD.bazel
Normal file
@@ -0,0 +1,21 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"attestation_test.go",
|
||||
"attester_slashing_test.go",
|
||||
"block_header_test.go",
|
||||
"deposit_test.go",
|
||||
"proposer_slashing_test.go",
|
||||
"sync_committee_test.go",
|
||||
"voluntary_exit_test.go",
|
||||
],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
shard_count = 4,
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/operations:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Operations_Attestation(t *testing.T) {
|
||||
operations.RunAttestationTest(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Operations_AttesterSlashing(t *testing.T) {
|
||||
operations.RunAttesterSlashingTest(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Operations_BlockHeader(t *testing.T) {
|
||||
operations.RunBlockHeaderTest(t, "mainnet")
|
||||
}
|
||||
11
testing/spectest/mainnet/capella/operations/deposit_test.go
Normal file
11
testing/spectest/mainnet/capella/operations/deposit_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Operations_Deposit(t *testing.T) {
|
||||
operations.RunDepositTest(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Operations_ProposerSlashing(t *testing.T) {
|
||||
operations.RunProposerSlashingTest(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Operations_SyncCommittee(t *testing.T) {
|
||||
operations.RunSyncCommitteeTest(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Operations_VoluntaryExit(t *testing.T) {
|
||||
operations.RunVoluntaryExitTest(t, "mainnet")
|
||||
}
|
||||
12
testing/spectest/mainnet/capella/rewards/BUILD.bazel
Normal file
12
testing/spectest/mainnet/capella/rewards/BUILD.bazel
Normal file
@@ -0,0 +1,12 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["rewards_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/rewards:go_default_library"],
|
||||
)
|
||||
11
testing/spectest/mainnet/capella/rewards/rewards_test.go
Normal file
11
testing/spectest/mainnet/capella/rewards/rewards_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package rewards
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/rewards"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Rewards(t *testing.T) {
|
||||
rewards.RunPrecomputeRewardsAndPenaltiesTests(t, "mainnet")
|
||||
}
|
||||
16
testing/spectest/mainnet/capella/sanity/BUILD.bazel
Normal file
16
testing/spectest/mainnet/capella/sanity/BUILD.bazel
Normal file
@@ -0,0 +1,16 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "medium",
|
||||
timeout = "short",
|
||||
srcs = [
|
||||
"blocks_test.go",
|
||||
"slots_test.go",
|
||||
],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/sanity:go_default_library"],
|
||||
)
|
||||
11
testing/spectest/mainnet/capella/sanity/blocks_test.go
Normal file
11
testing/spectest/mainnet/capella/sanity/blocks_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package sanity
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/sanity"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Sanity_Blocks(t *testing.T) {
|
||||
sanity.RunBlockProcessingTest(t, "mainnet", "sanity/blocks/pyspec_tests")
|
||||
}
|
||||
11
testing/spectest/mainnet/capella/sanity/slots_test.go
Normal file
11
testing/spectest/mainnet/capella/sanity/slots_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package sanity
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/sanity"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_Sanity_Slots(t *testing.T) {
|
||||
sanity.RunSlotProcessingTests(t, "mainnet")
|
||||
}
|
||||
12
testing/spectest/mainnet/capella/ssz_static/BUILD.bazel
Normal file
12
testing/spectest/mainnet/capella/ssz_static/BUILD.bazel
Normal file
@@ -0,0 +1,12 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["ssz_static_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_mainnet//:test_data",
|
||||
],
|
||||
tags = ["spectest"],
|
||||
deps = ["//testing/spectest/shared/capella/ssz_static:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package ssz_static
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/ssz_static"
|
||||
)
|
||||
|
||||
func TestMainnet_Capella_SSZStatic(t *testing.T) {
|
||||
ssz_static.RunSSZStaticTests(t, "mainnet")
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"effective_balance_updates_test.go",
|
||||
"eth1_data_reset_test.go",
|
||||
"historical_roots_update_test.go",
|
||||
"inactivity_updates_test.go",
|
||||
"justification_and_finalization_test.go",
|
||||
"participation_flag_updates_test.go",
|
||||
"randao_mixes_reset_test.go",
|
||||
"registry_updates_test.go",
|
||||
"rewards_and_penalties_test.go",
|
||||
"slashings_reset_test.go",
|
||||
"slashings_test.go",
|
||||
],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
],
|
||||
eth_network = "minimal",
|
||||
tags = [
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = ["//testing/spectest/shared/capella/epoch_processing:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_EffectiveBalanceUpdates(t *testing.T) {
|
||||
epoch_processing.RunEffectiveBalanceUpdatesTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_Eth1DataReset(t *testing.T) {
|
||||
epoch_processing.RunEth1DataResetTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_HistoricalRootsUpdate(t *testing.T) {
|
||||
epoch_processing.RunHistoricalRootsUpdateTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_InactivityUpdates(t *testing.T) {
|
||||
epoch_processing.RunInactivityUpdatesTest(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_JustificationAndFinalization(t *testing.T) {
|
||||
epoch_processing.RunJustificationAndFinalizationTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_ParticipationFlag(t *testing.T) {
|
||||
epoch_processing.RunParticipationFlagUpdatesTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_RandaoMixesReset(t *testing.T) {
|
||||
epoch_processing.RunRandaoMixesResetTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_ResetRegistryUpdates(t *testing.T) {
|
||||
epoch_processing.RunRegistryUpdatesTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_RewardsAndPenalties(t *testing.T) {
|
||||
epoch_processing.RunRewardsAndPenaltiesTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_SlashingsReset(t *testing.T) {
|
||||
epoch_processing.RunSlashingsResetTests(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package epoch_processing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/epoch_processing"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_EpochProcessing_Slashings(t *testing.T) {
|
||||
epoch_processing.RunSlashingsTests(t, "minimal")
|
||||
}
|
||||
17
testing/spectest/minimal/capella/finality/BUILD.bazel
Normal file
17
testing/spectest/minimal/capella/finality/BUILD.bazel
Normal file
@@ -0,0 +1,17 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["finality_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
],
|
||||
eth_network = "minimal",
|
||||
shard_count = 4,
|
||||
tags = [
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = ["//testing/spectest/shared/capella/finality:go_default_library"],
|
||||
)
|
||||
11
testing/spectest/minimal/capella/finality/finality_test.go
Normal file
11
testing/spectest/minimal/capella/finality/finality_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package finality
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/finality"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_Finality(t *testing.T) {
|
||||
finality.RunFinalityTest(t, "minimal")
|
||||
}
|
||||
17
testing/spectest/minimal/capella/fork/BUILD.bazel
Normal file
17
testing/spectest/minimal/capella/fork/BUILD.bazel
Normal file
@@ -0,0 +1,17 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["upgrade_to_capella_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
],
|
||||
eth_network = "minimal",
|
||||
shard_count = 4,
|
||||
tags = [
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = ["//testing/spectest/shared/capella/fork:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package fork
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/fork"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_UpgradeToCapella(t *testing.T) {
|
||||
fork.RunUpgradeToCapella(t, "minimal")
|
||||
}
|
||||
21
testing/spectest/minimal/capella/forkchoice/BUILD.bazel
Normal file
21
testing/spectest/minimal/capella/forkchoice/BUILD.bazel
Normal file
@@ -0,0 +1,21 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "enormous",
|
||||
timeout = "short",
|
||||
srcs = ["forkchoice_test.go"],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
],
|
||||
eth_network = "minimal",
|
||||
tags = [
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = [
|
||||
"//config/features:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/spectest/shared/common/forkchoice:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/config/features"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/common/forkchoice"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_Forkchoice(t *testing.T) {
|
||||
resetCfg := features.InitWithReset(&features.Flags{
|
||||
EnableDefensivePull: false,
|
||||
DisablePullTips: true,
|
||||
})
|
||||
defer resetCfg()
|
||||
forkchoice.Run(t, "minimal", version.Capella)
|
||||
}
|
||||
26
testing/spectest/minimal/capella/operations/BUILD.bazel
Normal file
26
testing/spectest/minimal/capella/operations/BUILD.bazel
Normal file
@@ -0,0 +1,26 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"attestation_test.go",
|
||||
"attester_slashing_test.go",
|
||||
"block_header_test.go",
|
||||
"bls_to_execution_change_test.go",
|
||||
"deposit_test.go",
|
||||
"proposer_slashing_test.go",
|
||||
"sync_committee_test.go",
|
||||
"voluntary_exit_test.go",
|
||||
"withdrawals_test.go",
|
||||
],
|
||||
data = glob(["*.yaml"]) + [
|
||||
"@consensus_spec_tests_minimal//:test_data",
|
||||
],
|
||||
eth_network = "minimal",
|
||||
tags = [
|
||||
"minimal",
|
||||
"spectest",
|
||||
],
|
||||
deps = ["//testing/spectest/shared/capella/operations:go_default_library"],
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_Operations_Attestation(t *testing.T) {
|
||||
operations.RunAttestationTest(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_Operations_AttesterSlashing(t *testing.T) {
|
||||
operations.RunAttesterSlashingTest(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_Operations_BlockHeader(t *testing.T) {
|
||||
operations.RunBlockHeaderTest(t, "minimal")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_Operations_BLSToExecutionChange(t *testing.T) {
|
||||
operations.RunBLSToExecutionChangeTest(t, "minimal")
|
||||
}
|
||||
11
testing/spectest/minimal/capella/operations/deposit_test.go
Normal file
11
testing/spectest/minimal/capella/operations/deposit_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package operations
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/spectest/shared/capella/operations"
|
||||
)
|
||||
|
||||
func TestMinimal_Capella_Operations_Deposit(t *testing.T) {
|
||||
operations.RunDepositTest(t, "minimal")
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user