mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 13:58:09 -05:00
Compare commits
350 Commits
manu
...
kiln-debug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90bd683567 | ||
|
|
a1cfded8cf | ||
|
|
8731a74afe | ||
|
|
bb3ea38a76 | ||
|
|
f59aa60f77 | ||
|
|
42129c07c2 | ||
|
|
13cefc61a1 | ||
|
|
2338d3a874 | ||
|
|
dfd7854a4f | ||
|
|
5c39ddacd1 | ||
|
|
e0e8c30686 | ||
|
|
ce6005fb28 | ||
|
|
c7b0e819f4 | ||
|
|
a6df54882c | ||
|
|
172606bc7b | ||
|
|
66642b553b | ||
|
|
763b81ce79 | ||
|
|
ac6ecbac0b | ||
|
|
1130d4af22 | ||
|
|
d83c9cf43e | ||
|
|
a8a30a5305 | ||
|
|
83ee276362 | ||
|
|
dce3d1e8ea | ||
|
|
bd255a5790 | ||
|
|
c00e69d49f | ||
|
|
dd8fb34e70 | ||
|
|
ad400fcf6e | ||
|
|
7adf8d78ef | ||
|
|
6852310a35 | ||
|
|
b5cf982a57 | ||
|
|
2f8bdb43d1 | ||
|
|
fea3376bf9 | ||
|
|
0aae327d40 | ||
|
|
7d4008910f | ||
|
|
3aaf49de42 | ||
|
|
66774b5e66 | ||
|
|
43d53f5c42 | ||
|
|
053876643e | ||
|
|
f30b261abf | ||
|
|
a9b74ae10a | ||
|
|
fc2e4e7d62 | ||
|
|
7e83bc0cc4 | ||
|
|
f1a2d932be | ||
|
|
21227e3efd | ||
|
|
a2e86e6fb2 | ||
|
|
aad1ea3e6c | ||
|
|
56277d5e21 | ||
|
|
ee31675b64 | ||
|
|
48045e96c6 | ||
|
|
5aa80098cb | ||
|
|
43e6496a91 | ||
|
|
dd3d421dec | ||
|
|
9c96f80db9 | ||
|
|
eb78422563 | ||
|
|
0d85422ebc | ||
|
|
293b9761ef | ||
|
|
8f9cfb0e0a | ||
|
|
b9945d21dd | ||
|
|
dc965d3a23 | ||
|
|
7ef03b767d | ||
|
|
0a1e93a0b7 | ||
|
|
876fd5bfb1 | ||
|
|
1a4c073337 | ||
|
|
11e00f61b1 | ||
|
|
2c6e3916bb | ||
|
|
8dd9e0f850 | ||
|
|
7529ceda2f | ||
|
|
37baf27b5b | ||
|
|
c812117e68 | ||
|
|
f289f690da | ||
|
|
4d278de34d | ||
|
|
49e8b9f1fe | ||
|
|
17cc44a3fd | ||
|
|
0c41a34b2e | ||
|
|
2716184852 | ||
|
|
d056b21f09 | ||
|
|
3ea8b79697 | ||
|
|
5566b2bb15 | ||
|
|
52171da8c8 | ||
|
|
ab9ece5263 | ||
|
|
29296de277 | ||
|
|
1d4477c6d4 | ||
|
|
649a345664 | ||
|
|
8d13ed12e1 | ||
|
|
ce86bfae66 | ||
|
|
7423c61292 | ||
|
|
8029648849 | ||
|
|
ce0bd748eb | ||
|
|
9fe7d5833c | ||
|
|
3ae6dc9068 | ||
|
|
c489687336 | ||
|
|
a37e0f19c3 | ||
|
|
ee1ee623c0 | ||
|
|
e62cdcea16 | ||
|
|
546939dd33 | ||
|
|
f6eb6cd6bf | ||
|
|
a08c809073 | ||
|
|
ef0435493d | ||
|
|
6f15d2b0b2 | ||
|
|
5b4a87c512 | ||
|
|
5d7704e3a9 | ||
|
|
c4093f8adb | ||
|
|
4724b8430f | ||
|
|
55c8922f51 | ||
|
|
7f8d66c919 | ||
|
|
e2e5a0d86c | ||
|
|
4acc40ffed | ||
|
|
acc528ff75 | ||
|
|
87395141e8 | ||
|
|
a69901bd7c | ||
|
|
72d2bc7ce1 | ||
|
|
aecd34a1ea | ||
|
|
1daae0f5cf | ||
|
|
1583c77bdf | ||
|
|
8baf2179b3 | ||
|
|
d41947c60d | ||
|
|
d8f9ecbd4d | ||
|
|
9da43e4170 | ||
|
|
d3756ea4ea | ||
|
|
66418ec0ff | ||
|
|
e3963094d4 | ||
|
|
a5240cf4b8 | ||
|
|
78a90af679 | ||
|
|
b280e796da | ||
|
|
1e32cd5596 | ||
|
|
72c1720704 | ||
|
|
b6fd9e5315 | ||
|
|
fa1509c970 | ||
|
|
f9fbda80c2 | ||
|
|
9a56a5d101 | ||
|
|
5e8c49c871 | ||
|
|
4c7daf7a1f | ||
|
|
c4454cae78 | ||
|
|
1cedf4ba9a | ||
|
|
4ce3da7ecc | ||
|
|
70a6fc4222 | ||
|
|
bb126a9829 | ||
|
|
99deee57d1 | ||
|
|
4c23401a3b | ||
|
|
9636fde1eb | ||
|
|
a424f523a1 | ||
|
|
68e75d5851 | ||
|
|
176ea137ee | ||
|
|
b15cd763b6 | ||
|
|
8e78eae897 | ||
|
|
f6883f2aa9 | ||
|
|
19782d2563 | ||
|
|
032cf433c5 | ||
|
|
fa656a86a5 | ||
|
|
5f414b3e82 | ||
|
|
41b8b1a0f8 | ||
|
|
1d36ecb98d | ||
|
|
80cd539297 | ||
|
|
f47b6af910 | ||
|
|
443df77bb3 | ||
|
|
94fe3884a0 | ||
|
|
7d6046276d | ||
|
|
4f77ad20c8 | ||
|
|
1b5a6d4195 | ||
|
|
eae0db383f | ||
|
|
b56bd9e9d8 | ||
|
|
481d8847c2 | ||
|
|
42d5416658 | ||
|
|
a1d8833749 | ||
|
|
695389b7bb | ||
|
|
a67b8610f0 | ||
|
|
29eceba4d2 | ||
|
|
4c34e5d424 | ||
|
|
569375286e | ||
|
|
924758a557 | ||
|
|
eedcb529fd | ||
|
|
30e796a4f1 | ||
|
|
ea6ca456e6 | ||
|
|
4b75b991dd | ||
|
|
8eaf391918 | ||
|
|
cbdb3c9e86 | ||
|
|
12754adddc | ||
|
|
08a5155ee3 | ||
|
|
f99a0419ef | ||
|
|
4ad31f9c05 | ||
|
|
26876d64d7 | ||
|
|
3450923661 | ||
|
|
aba628b56b | ||
|
|
5effb92d11 | ||
|
|
2b55368c99 | ||
|
|
327903b7bb | ||
|
|
77f815a39f | ||
|
|
80dc725412 | ||
|
|
263c18992e | ||
|
|
9e220f9052 | ||
|
|
99878d104c | ||
|
|
a870bf7a74 | ||
|
|
dc42ff382f | ||
|
|
53b78a38a3 | ||
|
|
b45826e731 | ||
|
|
7b59ecac5e | ||
|
|
9149178a9c | ||
|
|
51ef502b04 | ||
|
|
8d891821ee | ||
|
|
762863ce6a | ||
|
|
41f5fa7524 | ||
|
|
09744bac70 | ||
|
|
f5db847237 | ||
|
|
8600f70b0b | ||
|
|
6fe430de44 | ||
|
|
42a5f96d3f | ||
|
|
e7f0fcf202 | ||
|
|
5ae564f1bf | ||
|
|
719109c219 | ||
|
|
64533a4b0c | ||
|
|
9fecd761d7 | ||
|
|
f84c95667c | ||
|
|
9af081797e | ||
|
|
e4e9f12c8b | ||
|
|
2f4e8beae6 | ||
|
|
81c7b90d26 | ||
|
|
dd3d65ff18 | ||
|
|
ac5a227aeb | ||
|
|
33f4d5c3cc | ||
|
|
67d7f8baee | ||
|
|
3c54aef7b1 | ||
|
|
938c28c42e | ||
|
|
8ddb2c26c4 | ||
|
|
cf0e78c2f6 | ||
|
|
4c0b262fdc | ||
|
|
33e675e204 | ||
|
|
e599f6a8a1 | ||
|
|
49c9ab9fda | ||
|
|
f90dec287b | ||
|
|
12c36cff9d | ||
|
|
bc565d9ee6 | ||
|
|
db67d5bad8 | ||
|
|
3bc0c2be54 | ||
|
|
1bed9ef749 | ||
|
|
ec772beeaf | ||
|
|
56407dde02 | ||
|
|
445f17881e | ||
|
|
183d40d8f1 | ||
|
|
87bc6aa5e5 | ||
|
|
5b5065b01d | ||
|
|
ee1c567561 | ||
|
|
ff1416c98d | ||
|
|
471c94031f | ||
|
|
9863fb3d6a | ||
|
|
f3c2d1a00b | ||
|
|
5d8879a4df | ||
|
|
abea0a11bc | ||
|
|
80ce1603bd | ||
|
|
ca478244e0 | ||
|
|
8a864b66a1 | ||
|
|
72f3b9e84b | ||
|
|
493e95060f | ||
|
|
e7e1ecd72f | ||
|
|
c286ac8b87 | ||
|
|
bde315224c | ||
|
|
00520705bc | ||
|
|
c7fcd804d7 | ||
|
|
985ac2e848 | ||
|
|
f4a0e98926 | ||
|
|
5f93ff10ea | ||
|
|
544248f60f | ||
|
|
3b41968510 | ||
|
|
7fc418042a | ||
|
|
9a03946706 | ||
|
|
33dd6dd5f2 | ||
|
|
56542e1958 | ||
|
|
e82d7b4c0b | ||
|
|
6cb69d8ff0 | ||
|
|
70b55a0191 | ||
|
|
50f4951194 | ||
|
|
1a14f2368d | ||
|
|
bb8cad58f1 | ||
|
|
05412c1f0e | ||
|
|
b03441fed8 | ||
|
|
fa7d7cef69 | ||
|
|
1caa6c969f | ||
|
|
eeb7d5bbfb | ||
|
|
d7c7d150b1 | ||
|
|
63c4d2eb2b | ||
|
|
9de1f694a0 | ||
|
|
8a79d06cbd | ||
|
|
5290ad93b8 | ||
|
|
2128208ef7 | ||
|
|
296323719c | ||
|
|
5e9583ea85 | ||
|
|
17196e0f80 | ||
|
|
c50d54000d | ||
|
|
85b3061d1b | ||
|
|
0146c5317a | ||
|
|
fcbc48ffd9 | ||
|
|
76ee51af9d | ||
|
|
370b0b97ed | ||
|
|
990ebd3fe3 | ||
|
|
54449c72e8 | ||
|
|
1dbd0b98eb | ||
|
|
09c3896c6b | ||
|
|
d494845e19 | ||
|
|
4d0c0f7234 | ||
|
|
bfe570b1aa | ||
|
|
56db696823 | ||
|
|
d312e15db8 | ||
|
|
907d4cf7e6 | ||
|
|
891353d6ad | ||
|
|
0adc08660c | ||
|
|
de31425dcd | ||
|
|
2094e0f21f | ||
|
|
2c6f554500 | ||
|
|
18a1e07711 | ||
|
|
5e432f5aaa | ||
|
|
284e2696cb | ||
|
|
7547aaa6ce | ||
|
|
953315c2cc | ||
|
|
9662d06b08 | ||
|
|
ecaea26ace | ||
|
|
63819e2690 | ||
|
|
a6d0cd06b3 | ||
|
|
2dbe4f5e67 | ||
|
|
2689d6814d | ||
|
|
69a681ddc0 | ||
|
|
7f9f1fd36c | ||
|
|
57c97eb561 | ||
|
|
f0f94a8193 | ||
|
|
87b0bf2c2a | ||
|
|
d8ad317dec | ||
|
|
ab5f488cf4 | ||
|
|
296d7464ad | ||
|
|
221c542e4f | ||
|
|
7ad32aaa96 | ||
|
|
3dc0969c0c | ||
|
|
0e18e835c3 | ||
|
|
8adfbfc382 | ||
|
|
68b0b5e0ce | ||
|
|
eede309e0f | ||
|
|
b11628dc53 | ||
|
|
ea3ae22d3b | ||
|
|
02bb39ddeb | ||
|
|
1618c1f55d | ||
|
|
73c8493fd7 | ||
|
|
a4f59a4f15 | ||
|
|
3c497efdb8 | ||
|
|
9f5daafbb7 | ||
|
|
11d7ffdfa8 | ||
|
|
c26b3305e6 | ||
|
|
38d8b63fbf | ||
|
|
aea67405c8 | ||
|
|
57d830f8b3 | ||
|
|
ac4b1ef4ea | ||
|
|
1d32119f5a | ||
|
|
3540cc7b05 | ||
|
|
191e7767a6 |
@@ -48,6 +48,7 @@ go_library(
|
||||
"//beacon-chain/core/transition:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/filters:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
"//beacon-chain/forkchoice:go_default_library",
|
||||
"//beacon-chain/forkchoice/doubly-linked-tree:go_default_library",
|
||||
"//beacon-chain/forkchoice/protoarray:go_default_library",
|
||||
|
||||
@@ -5,15 +5,21 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
v1 "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -29,10 +35,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, headBlk block.Beac
|
||||
return nil, errors.New("nil head block")
|
||||
}
|
||||
// Must not call fork choice updated until the transition conditions are met on the Pow network.
|
||||
if isPreBellatrix(headBlk.Version()) {
|
||||
return nil, nil
|
||||
}
|
||||
isExecutionBlk, err := blocks.ExecutionBlock(headBlk.Body())
|
||||
isExecutionBlk, err := blocks.IsExecutionBlock(headBlk.Body())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not determine if block is execution block")
|
||||
}
|
||||
@@ -48,7 +51,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, headBlk block.Beac
|
||||
return nil, errors.Wrap(err, "could not get finalized block")
|
||||
}
|
||||
var finalizedHash []byte
|
||||
if isPreBellatrix(finalizedBlock.Block().Version()) {
|
||||
if blocks.IsPreBellatrixVersion(finalizedBlock.Block().Version()) {
|
||||
finalizedHash = params.BeaconConfig().ZeroHash[:]
|
||||
} else {
|
||||
payload, err := finalizedBlock.Block().Body().ExecutionPayload()
|
||||
@@ -64,8 +67,13 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, headBlk block.Beac
|
||||
FinalizedBlockHash: finalizedHash,
|
||||
}
|
||||
|
||||
// payload attribute is only required when requesting payload, here we are just updating fork choice, so it is nil.
|
||||
payloadID, _, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, nil /*payload attribute*/)
|
||||
nextSlot := s.CurrentSlot() + 1
|
||||
hasAttr, attr, vid, err := s.getPayloadAttribute(ctx, s.headState(ctx), nextSlot)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get payload attribute")
|
||||
}
|
||||
|
||||
payloadID, _, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, attr)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case v1.ErrAcceptedSyncingPayloadStatus:
|
||||
@@ -82,6 +90,9 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, headBlk block.Beac
|
||||
if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, headRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "could not set block to valid")
|
||||
}
|
||||
if hasAttr {
|
||||
s.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(nextSlot, vid, bytesutil.BytesToUint64BigEndian(payloadID[:]))
|
||||
}
|
||||
return payloadID, nil
|
||||
}
|
||||
|
||||
@@ -93,7 +104,7 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion, postSta
|
||||
|
||||
// Execution payload is only supported in Bellatrix and beyond. Pre
|
||||
// merge blocks are never optimistic
|
||||
if isPreBellatrix(postStateVersion) {
|
||||
if blocks.IsPreBellatrixVersion(postStateVersion) {
|
||||
return s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, root)
|
||||
}
|
||||
if err := helpers.BeaconBlockIsNil(blk); err != nil {
|
||||
@@ -130,7 +141,7 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion, postSta
|
||||
}
|
||||
|
||||
// During the transition event, the transition block should be verified for sanity.
|
||||
if isPreBellatrix(preStateVersion) {
|
||||
if blocks.IsPreBellatrixVersion(preStateVersion) {
|
||||
// Handle case where pre-state is Altair but block contains payload.
|
||||
// To reach here, the block must have contained a valid payload.
|
||||
return s.validateMergeBlock(ctx, blk)
|
||||
@@ -145,11 +156,6 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion, postSta
|
||||
return s.validateMergeBlock(ctx, blk)
|
||||
}
|
||||
|
||||
// isPreBellatrix returns true if input version is before bellatrix fork.
|
||||
func isPreBellatrix(v int) bool {
|
||||
return v == version.Phase0 || v == version.Altair
|
||||
}
|
||||
|
||||
// optimisticCandidateBlock returns true if this block can be optimistically synced.
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
@@ -178,7 +184,7 @@ func (s *Service) optimisticCandidateBlock(ctx context.Context, blk block.Beacon
|
||||
return false, errNilParentInDB
|
||||
}
|
||||
|
||||
parentIsExecutionBlock, err := blocks.ExecutionBlock(parent.Block().Body())
|
||||
parentIsExecutionBlock, err := blocks.IsExecutionBlock(parent.Block().Body())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -194,5 +200,46 @@ func (s *Service) optimisticCandidateBlock(ctx context.Context, blk block.Beacon
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return blocks.ExecutionBlock(jBlock.Block().Body())
|
||||
return blocks.IsExecutionBlock(jBlock.Block().Body())
|
||||
}
|
||||
|
||||
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot types.Slot) (bool, *enginev1.PayloadAttributes, types.ValidatorIndex, error) {
|
||||
vId, _, ok := s.cfg.ProposerSlotIndexCache.GetProposerPayloadIDs(slot)
|
||||
if !ok {
|
||||
return false, nil, 0, nil
|
||||
}
|
||||
st = st.Copy()
|
||||
st, err := transition.ProcessSlotsIfPossible(ctx, st, slot)
|
||||
if err != nil {
|
||||
return false, nil, 0, err
|
||||
}
|
||||
random, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
|
||||
if err != nil {
|
||||
return false, nil, 0, nil
|
||||
}
|
||||
feeRecipient := params.BeaconConfig().DefaultFeeRecipient
|
||||
recipient, err := s.cfg.BeaconDB.FeeRecipientByValidatorID(ctx, vId)
|
||||
switch err == nil {
|
||||
case true:
|
||||
feeRecipient = recipient
|
||||
case errors.As(err, kv.ErrNotFoundFeeRecipient):
|
||||
if feeRecipient.String() == fieldparams.EthBurnAddressHex {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"validatorIndex": vId,
|
||||
"burnAddress": fieldparams.EthBurnAddressHex,
|
||||
}).Error("Fee recipient not set. Using burn address")
|
||||
}
|
||||
default:
|
||||
return false, nil, 0, errors.Wrap(err, "could not get fee recipient in db")
|
||||
}
|
||||
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
|
||||
if err != nil {
|
||||
return false, nil, 0, err
|
||||
}
|
||||
attr := &enginev1.PayloadAttributes{
|
||||
Timestamp: uint64(t.Unix()),
|
||||
PrevRandao: random,
|
||||
SuggestedFeeRecipient: feeRecipient.Bytes(),
|
||||
}
|
||||
return true, attr, vId, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||
engine "github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1"
|
||||
@@ -21,6 +24,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
logTest "github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
|
||||
func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
||||
@@ -589,3 +593,43 @@ func Test_IsOptimisticShallowExecutionParent(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, candidate)
|
||||
}
|
||||
|
||||
func Test_GetPayloadAttribute(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
beaconDB := testDB.SetupDB(t)
|
||||
opts := []Option{
|
||||
WithDatabase(beaconDB),
|
||||
WithStateGen(stategen.New(beaconDB)),
|
||||
WithProposerIdsCache(cache.NewProposerPayloadIDsCache()),
|
||||
}
|
||||
|
||||
// Cache miss
|
||||
service, err := NewService(ctx, opts...)
|
||||
require.NoError(t, err)
|
||||
hasPayload, _, vId, err := service.getPayloadAttribute(ctx, nil, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, hasPayload)
|
||||
require.Equal(t, types.ValidatorIndex(0), vId)
|
||||
|
||||
// Cache hit, advance state, no fee recipient
|
||||
suggestedVid := types.ValidatorIndex(1)
|
||||
slot := types.Slot(1)
|
||||
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, 0)
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
hook := logTest.NewGlobal()
|
||||
hasPayload, attr, vId, err := service.getPayloadAttribute(ctx, st, slot)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, hasPayload)
|
||||
require.Equal(t, suggestedVid, vId)
|
||||
require.Equal(t, fieldparams.EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient).String())
|
||||
require.LogsContain(t, hook, "Fee recipient not set. Using burn address")
|
||||
|
||||
// Cache hit, advance state, has fee recipient
|
||||
suggestedAddr := common.HexToAddress("123")
|
||||
service.cfg.BeaconDB.SaveFeeRecipientsByValidatorIDs(ctx, []types.ValidatorIndex{suggestedVid}, []common.Address{suggestedAddr})
|
||||
service.cfg.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, suggestedVid, 0)
|
||||
hasPayload, attr, vId, err = service.getPayloadAttribute(ctx, st, slot)
|
||||
require.Equal(t, true, hasPayload)
|
||||
require.Equal(t, suggestedVid, vId)
|
||||
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient))
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package blockchain
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
@@ -67,6 +68,14 @@ func WithDepositCache(c *depositcache.DepositCache) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithProposerIdsCache --.
|
||||
func WithProposerIdsCache(c *cache.ProposerPayloadIDsCache) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.ProposerSlotIndexCache = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAttestationPool for attestation lifecycle after chain inclusion.
|
||||
func WithAttestationPool(p attestations.Pool) Option {
|
||||
return func(s *Service) error {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -535,7 +536,7 @@ func (s *Service) insertBlockToForkChoiceStore(ctx context.Context, blk block.Be
|
||||
|
||||
func getBlockPayloadHash(blk block.BeaconBlock) ([32]byte, error) {
|
||||
payloadHash := [32]byte{}
|
||||
if isPreBellatrix(blk.Version()) {
|
||||
if blocks.IsPreBellatrixVersion(blk.Version()) {
|
||||
return payloadHash, nil
|
||||
}
|
||||
payload, err := blk.Body().ExecutionPayload()
|
||||
|
||||
@@ -75,6 +75,7 @@ type config struct {
|
||||
ChainStartFetcher powchain.ChainStartFetcher
|
||||
BeaconDB db.HeadAccessDatabase
|
||||
DepositCache *depositcache.DepositCache
|
||||
ProposerSlotIndexCache *cache.ProposerPayloadIDsCache
|
||||
AttPool attestations.Pool
|
||||
ExitPool voluntaryexits.PoolManager
|
||||
SlashingPool slashings.PoolManager
|
||||
|
||||
2
beacon-chain/cache/BUILD.bazel
vendored
2
beacon-chain/cache/BUILD.bazel
vendored
@@ -13,6 +13,7 @@ go_library(
|
||||
"common.go",
|
||||
"doc.go",
|
||||
"error.go",
|
||||
"payload_id.go",
|
||||
"proposer_indices.go",
|
||||
"proposer_indices_disabled.go", # keep
|
||||
"proposer_indices_type.go",
|
||||
@@ -61,6 +62,7 @@ go_test(
|
||||
"checkpoint_state_test.go",
|
||||
"committee_fuzz_test.go",
|
||||
"committee_test.go",
|
||||
"payload_id_test.go",
|
||||
"proposer_indices_test.go",
|
||||
"skip_slot_cache_test.go",
|
||||
"subnet_ids_test.go",
|
||||
|
||||
53
beacon-chain/cache/payload_id.go
vendored
Normal file
53
beacon-chain/cache/payload_id.go
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
)
|
||||
|
||||
const vIdLength = 8
|
||||
const pIdLength = 8
|
||||
const vpIdsLength = vIdLength + pIdLength
|
||||
|
||||
type ProposerPayloadIDsCache struct {
|
||||
slotToProposerAndPayloadIDs map[types.Slot][vpIdsLength]byte
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func NewProposerPayloadIDsCache() *ProposerPayloadIDsCache {
|
||||
return &ProposerPayloadIDsCache{
|
||||
slotToProposerAndPayloadIDs: make(map[types.Slot][vpIdsLength]byte),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ProposerPayloadIDsCache) GetProposerPayloadIDs(slot types.Slot) (types.ValidatorIndex, uint64, bool) {
|
||||
f.RLock()
|
||||
defer f.RUnlock()
|
||||
ids, ok := f.slotToProposerAndPayloadIDs[slot]
|
||||
if !ok {
|
||||
return 0, 0, false
|
||||
}
|
||||
vId := ids[:vIdLength]
|
||||
pId := ids[vIdLength:]
|
||||
return types.ValidatorIndex(bytesutil.BytesToUint64BigEndian(vId)), bytesutil.BytesToUint64BigEndian(pId), true
|
||||
}
|
||||
|
||||
func (f *ProposerPayloadIDsCache) SetProposerAndPayloadIDs(slot types.Slot, vId types.ValidatorIndex, pId uint64) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
var vIdBytes [vIdLength]byte
|
||||
copy(vIdBytes[:], bytesutil.Uint64ToBytesBigEndian(uint64(vId)))
|
||||
var pIdBytes [pIdLength]byte
|
||||
copy(pIdBytes[:], bytesutil.Uint64ToBytesBigEndian(pId))
|
||||
|
||||
var bytes [vpIdsLength]byte
|
||||
copy(bytes[:], append(vIdBytes[:], pIdBytes[:]...))
|
||||
|
||||
_, ok := f.slotToProposerAndPayloadIDs[slot]
|
||||
if !ok || (ok && pId != 0) {
|
||||
f.slotToProposerAndPayloadIDs[slot] = bytes
|
||||
|
||||
}
|
||||
}
|
||||
34
beacon-chain/cache/payload_id_test.go
vendored
Normal file
34
beacon-chain/cache/payload_id_test.go
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func TestValidatorPayloadIDsCache_GetAndSaveValidatorPayloadIDs(t *testing.T) {
|
||||
cache := NewValidatorPayloadIDsCache()
|
||||
i, p, ok := cache.GetValidatorPayloadIDs(0)
|
||||
require.Equal(t, false, ok)
|
||||
require.Equal(t, types.ValidatorIndex(0), i)
|
||||
require.Equal(t, uint64(0), p)
|
||||
|
||||
slot := types.Slot(1234)
|
||||
vid := types.ValidatorIndex(34234324)
|
||||
pid := uint64(234234)
|
||||
cache.SetValidatorAndPayloadIDs(slot, vid, pid)
|
||||
i, p, ok = cache.GetValidatorPayloadIDs(slot)
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, vid, i)
|
||||
require.Equal(t, pid, p)
|
||||
|
||||
slot = types.Slot(9456456)
|
||||
vid = types.ValidatorIndex(6786745)
|
||||
pid = uint64(87687)
|
||||
cache.SetValidatorAndPayloadIDs(slot, vid, pid)
|
||||
i, p, ok = cache.GetValidatorPayloadIDs(slot)
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, vid, i)
|
||||
require.Equal(t, pid, p)
|
||||
}
|
||||
@@ -45,6 +45,7 @@ go_library(
|
||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||
"//proto/prysm/v1alpha1/block:go_default_library",
|
||||
"//proto/prysm/v1alpha1/slashings:go_default_library",
|
||||
"//proto/prysm/v1alpha1/wrapper:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
|
||||
@@ -2,7 +2,6 @@ package blocks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -14,81 +13,74 @@ import (
|
||||
enginev1 "github.com/prysmaticlabs/prysm/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
// MergeTransitionComplete returns true if the transition to Bellatrix has completed.
|
||||
// IsMergeTransitionComplete returns true if the transition to Bellatrix has completed.
|
||||
// Meaning the payload header in beacon state is not `ExecutionPayloadHeader()` (i.e. not empty).
|
||||
//
|
||||
// Spec code:
|
||||
// def is_merge_transition_complete(state: BeaconState) -> bool:
|
||||
// return state.latest_execution_payload_header != ExecutionPayloadHeader()
|
||||
//
|
||||
// Deprecated: Use `IsMergeTransitionBlockUsingPayloadHeader` instead.
|
||||
func MergeTransitionComplete(st state.BeaconState) (bool, error) {
|
||||
func IsMergeTransitionComplete(st state.BeaconState) (bool, error) {
|
||||
if st == nil {
|
||||
return false, errors.New("nil state")
|
||||
}
|
||||
if IsPreBellatrixVersion(st.Version()) {
|
||||
return false, nil
|
||||
}
|
||||
h, err := st.LatestExecutionPayloadHeader()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return !isEmptyHeader(h), nil
|
||||
}
|
||||
|
||||
// MergeTransitionBlock returns true if the input block is the terminal merge block.
|
||||
// Meaning the header in beacon state is `ExecutionPayloadHeader()` (i.e. empty).
|
||||
// And the input block has a non-empty header.
|
||||
//
|
||||
// Spec code:
|
||||
// def is_merge_transition_block(state: BeaconState, body: BeaconBlockBody) -> bool:
|
||||
// return not is_merge_transition_complete(state) and body.execution_payload != ExecutionPayload()
|
||||
func MergeTransitionBlock(st state.BeaconState, body block.BeaconBlockBody) (bool, error) {
|
||||
mergeComplete, err := MergeTransitionComplete(st)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if mergeComplete {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return ExecutionBlock(body)
|
||||
}
|
||||
|
||||
// IsMergeTransitionBlockUsingPayloadHeader returns true if the input block is the terminal merge block.
|
||||
// Terminal merge block must be associated with an empty payload header.
|
||||
// This is an optimized version of MergeTransitionComplete where beacon state is not required as an argument.
|
||||
func IsMergeTransitionBlockUsingPayloadHeader(h *ethpb.ExecutionPayloadHeader, body block.BeaconBlockBody) (bool, error) {
|
||||
if h == nil || body == nil {
|
||||
return false, errors.New("nil header or block body")
|
||||
}
|
||||
if !isEmptyHeader(h) {
|
||||
return false, nil
|
||||
}
|
||||
return ExecutionBlock(body)
|
||||
return IsExecutionBlock(body)
|
||||
}
|
||||
|
||||
// ExecutionBlock returns whether the block has a non-empty ExecutionPayload.
|
||||
// IsExecutionBlock returns whether the block has a non-empty ExecutionPayload.
|
||||
//
|
||||
// Spec code:
|
||||
// def is_execution_block(block: BeaconBlock) -> bool:
|
||||
// return block.body.execution_payload != ExecutionPayload()
|
||||
func ExecutionBlock(body block.BeaconBlockBody) (bool, error) {
|
||||
func IsExecutionBlock(body block.BeaconBlockBody) (bool, error) {
|
||||
if body == nil {
|
||||
return false, errors.New("nil block body")
|
||||
}
|
||||
payload, err := body.ExecutionPayload()
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "ExecutionPayload is not supported in") {
|
||||
return false, nil
|
||||
}
|
||||
switch {
|
||||
case errors.Is(err, wrapper.ErrUnsupportedField):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, err
|
||||
default:
|
||||
}
|
||||
return !isEmptyPayload(payload), nil
|
||||
}
|
||||
|
||||
// ExecutionEnabled returns true if the beacon chain can begin executing.
|
||||
// IsExecutionEnabled returns true if the beacon chain can begin executing.
|
||||
// Meaning the payload header is beacon state is non-empty or the payload in block body is non-empty.
|
||||
//
|
||||
// Spec code:
|
||||
// def is_execution_enabled(state: BeaconState, body: BeaconBlockBody) -> bool:
|
||||
// return is_merge_block(state, body) or is_merge_complete(state)
|
||||
// Deprecated: Use `IsExecutionEnabledUsingHeader` instead.
|
||||
func ExecutionEnabled(st state.BeaconState, body block.BeaconBlockBody) (bool, error) {
|
||||
if st.Version() == version.Phase0 || st.Version() == version.Altair {
|
||||
func IsExecutionEnabled(st state.BeaconState, body block.BeaconBlockBody) (bool, error) {
|
||||
if st == nil || body == nil {
|
||||
return false, errors.New("nil state or block body")
|
||||
}
|
||||
if IsPreBellatrixVersion(st.Version()) {
|
||||
return false, nil
|
||||
}
|
||||
header, err := st.LatestExecutionPayloadHeader()
|
||||
@@ -99,12 +91,17 @@ func ExecutionEnabled(st state.BeaconState, body block.BeaconBlockBody) (bool, e
|
||||
}
|
||||
|
||||
// IsExecutionEnabledUsingHeader returns true if the execution is enabled using post processed payload header and block body.
|
||||
// This is an optimized version of ExecutionEnabled where beacon state is not required as an argument.
|
||||
// This is an optimized version of IsExecutionEnabled where beacon state is not required as an argument.
|
||||
func IsExecutionEnabledUsingHeader(header *ethpb.ExecutionPayloadHeader, body block.BeaconBlockBody) (bool, error) {
|
||||
if !isEmptyHeader(header) {
|
||||
return true, nil
|
||||
}
|
||||
return ExecutionBlock(body)
|
||||
return IsExecutionBlock(body)
|
||||
}
|
||||
|
||||
// IsPreBellatrixVersion returns true if input version is before bellatrix fork.
|
||||
func IsPreBellatrixVersion(v int) bool {
|
||||
return v == version.Phase0 || v == version.Altair
|
||||
}
|
||||
|
||||
// ValidatePayloadWhenMergeCompletes validates if payload is valid versus input beacon state.
|
||||
@@ -115,7 +112,7 @@ func IsExecutionEnabledUsingHeader(header *ethpb.ExecutionPayloadHeader, body bl
|
||||
// if is_merge_complete(state):
|
||||
// assert payload.parent_hash == state.latest_execution_payload_header.block_hash
|
||||
func ValidatePayloadWhenMergeCompletes(st state.BeaconState, payload *enginev1.ExecutionPayload) error {
|
||||
complete, err := MergeTransitionComplete(st)
|
||||
complete, err := IsMergeTransitionComplete(st)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
)
|
||||
|
||||
func Test_MergeComplete(t *testing.T) {
|
||||
func Test_IsMergeComplete(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload *ethpb.ExecutionPayloadHeader
|
||||
@@ -160,7 +160,7 @@ func Test_MergeComplete(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
|
||||
require.NoError(t, st.SetLatestExecutionPayloadHeader(tt.payload))
|
||||
got, err := blocks.MergeTransitionComplete(st)
|
||||
got, err := blocks.IsMergeTransitionComplete(st)
|
||||
require.NoError(t, err)
|
||||
if got != tt.want {
|
||||
t.Errorf("mergeComplete() got = %v, want %v", got, tt.want)
|
||||
@@ -169,187 +169,6 @@ func Test_MergeComplete(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MergeBlock(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload *enginev1.ExecutionPayload
|
||||
header *ethpb.ExecutionPayloadHeader
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "empty header, empty payload",
|
||||
payload: emptyPayload(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "non-empty header, empty payload",
|
||||
payload: emptyPayload(),
|
||||
header: func() *ethpb.ExecutionPayloadHeader {
|
||||
h := emptyPayloadHeader()
|
||||
h.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return h
|
||||
}(),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has parent hash",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has fee recipient",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.FeeRecipient = bytesutil.PadTo([]byte{'a'}, fieldparams.FeeRecipientLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has state root",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.StateRoot = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has receipt root",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.ReceiptsRoot = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has logs bloom",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.LogsBloom = bytesutil.PadTo([]byte{'a'}, fieldparams.LogsBloomLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has random",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.PrevRandao = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has base fee",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.BaseFeePerGas = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has block hash",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.BlockHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has tx",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.Transactions = [][]byte{{'a'}}
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has extra data",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.ExtraData = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has block number",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.BlockNumber = 1
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has gas limit",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.GasLimit = 1
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has gas used",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.GasUsed = 1
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, payload has timestamp",
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.Timestamp = 1
|
||||
return p
|
||||
}(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
|
||||
require.NoError(t, st.SetLatestExecutionPayloadHeader(tt.header))
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Body.ExecutionPayload = tt.payload
|
||||
body, err := wrapper.WrappedBellatrixBeaconBlockBody(blk.Block.Body)
|
||||
require.NoError(t, err)
|
||||
got, err := blocks.MergeTransitionBlock(st, body)
|
||||
require.NoError(t, err)
|
||||
if got != tt.want {
|
||||
t.Errorf("MergeTransitionBlock() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_IsMergeTransitionBlockUsingPayloadHeader(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -556,14 +375,90 @@ func Test_IsExecutionBlock(t *testing.T) {
|
||||
blk.Block.Body.ExecutionPayload = tt.payload
|
||||
wrappedBlock, err := wrapper.WrappedBellatrixBeaconBlock(blk.Block)
|
||||
require.NoError(t, err)
|
||||
got, err := blocks.ExecutionBlock(wrappedBlock.Body())
|
||||
got, err := blocks.IsExecutionBlock(wrappedBlock.Body())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ExecutionEnabled(t *testing.T) {
|
||||
func Test_IsExecutionEnabled(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload *enginev1.ExecutionPayload
|
||||
header *ethpb.ExecutionPayloadHeader
|
||||
useAltairSt bool
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "use older than bellatrix state",
|
||||
payload: emptyPayload(),
|
||||
header: emptyPayloadHeader(),
|
||||
useAltairSt: true,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "empty header, empty payload",
|
||||
payload: emptyPayload(),
|
||||
header: emptyPayloadHeader(),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "non-empty header, empty payload",
|
||||
payload: emptyPayload(),
|
||||
header: func() *ethpb.ExecutionPayloadHeader {
|
||||
h := emptyPayloadHeader()
|
||||
h.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return h
|
||||
}(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "empty header, non-empty payload",
|
||||
header: emptyPayloadHeader(),
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.Timestamp = 1
|
||||
return p
|
||||
}(),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "non-empty header, non-empty payload",
|
||||
header: func() *ethpb.ExecutionPayloadHeader {
|
||||
h := emptyPayloadHeader()
|
||||
h.ParentHash = bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength)
|
||||
return h
|
||||
}(),
|
||||
payload: func() *enginev1.ExecutionPayload {
|
||||
p := emptyPayload()
|
||||
p.Timestamp = 1
|
||||
return p
|
||||
}(),
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
|
||||
require.NoError(t, st.SetLatestExecutionPayloadHeader(tt.header))
|
||||
blk := util.NewBeaconBlockBellatrix()
|
||||
blk.Block.Body.ExecutionPayload = tt.payload
|
||||
body, err := wrapper.WrappedBellatrixBeaconBlockBody(blk.Block.Body)
|
||||
require.NoError(t, err)
|
||||
if tt.useAltairSt {
|
||||
st, _ = util.DeterministicGenesisStateAltair(t, 1)
|
||||
}
|
||||
got, err := blocks.IsExecutionEnabled(st, body)
|
||||
require.NoError(t, err)
|
||||
if got != tt.want {
|
||||
t.Errorf("IsExecutionEnabled() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_IsExecutionEnabledUsingHeader(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload *enginev1.ExecutionPayload
|
||||
@@ -696,7 +591,7 @@ func Test_IsExecutionEnabledUsingHeader(t *testing.T) {
|
||||
got, err := blocks.IsExecutionEnabledUsingHeader(tt.header, body)
|
||||
require.NoError(t, err)
|
||||
if got != tt.want {
|
||||
t.Errorf("ExecutionEnabled() got = %v, want %v", got, tt.want)
|
||||
t.Errorf("IsExecutionEnabled() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -904,7 +799,7 @@ func BenchmarkBellatrixComplete(b *testing.B) {
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := blocks.MergeTransitionComplete(st)
|
||||
_, err := blocks.IsMergeTransitionComplete(st)
|
||||
require.NoError(b, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,8 +176,7 @@ func CommitteeAssignments(
|
||||
}
|
||||
proposerIndexToSlots := make(map[types.ValidatorIndex][]types.Slot, params.BeaconConfig().SlotsPerEpoch)
|
||||
// Proposal epochs do not have a look ahead, so we skip them over here.
|
||||
validProposalEpoch := epoch < nextEpoch
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch && validProposalEpoch; slot++ {
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
||||
// Skip proposer assignment for genesis slot.
|
||||
if slot == 0 {
|
||||
continue
|
||||
|
||||
@@ -285,20 +285,18 @@ func ProcessBlockForStateRoot(
|
||||
return nil, errors.Wrap(err, "could not process block header")
|
||||
}
|
||||
|
||||
if state.Version() == version.Bellatrix {
|
||||
enabled, err := b.ExecutionEnabled(state, blk.Body())
|
||||
enabled, err := b.IsExecutionEnabled(state, blk.Body())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not check if execution is enabled")
|
||||
}
|
||||
if enabled {
|
||||
payload, err := blk.Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not check if execution is enabled")
|
||||
return nil, err
|
||||
}
|
||||
if enabled {
|
||||
payload, err := blk.Body().ExecutionPayload()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
state, err = b.ProcessPayload(state, payload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process execution payload")
|
||||
}
|
||||
state, err = b.ProcessPayload(state, payload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not process execution payload")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ go_library(
|
||||
"//api/gateway:go_default_library",
|
||||
"//async/event:go_default_library",
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
"//beacon-chain/db:go_default_library",
|
||||
"//beacon-chain/db/kv:go_default_library",
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
apigateway "github.com/prysmaticlabs/prysm/api/gateway"
|
||||
"github.com/prysmaticlabs/prysm/async/event"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
|
||||
@@ -91,6 +92,7 @@ type BeaconNode struct {
|
||||
slashingsPool slashings.PoolManager
|
||||
syncCommitteePool synccommittee.Pool
|
||||
depositCache *depositcache.DepositCache
|
||||
proposerIdsCache *cache.ProposerPayloadIDsCache
|
||||
stateFeed *event.Feed
|
||||
blockFeed *event.Feed
|
||||
opFeed *event.Feed
|
||||
@@ -146,6 +148,7 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) {
|
||||
slasherBlockHeadersFeed: new(event.Feed),
|
||||
slasherAttestationsFeed: new(event.Feed),
|
||||
serviceFlagOpts: &serviceFlagOpts{},
|
||||
proposerIdsCache: cache.NewProposerPayloadIDsCache(),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
@@ -572,6 +575,7 @@ func (b *BeaconNode) registerBlockchainService() error {
|
||||
blockchain.WithStateGen(b.stateGen),
|
||||
blockchain.WithSlasherAttestationsFeed(b.slasherAttestationsFeed),
|
||||
blockchain.WithFinalizedStateAtStartUp(b.finalizedStateAtStartUp),
|
||||
blockchain.WithProposerIdsCache(b.proposerIdsCache),
|
||||
)
|
||||
blockchainService, err := blockchain.NewService(b.ctx, opts...)
|
||||
if err != nil {
|
||||
@@ -789,6 +793,7 @@ func (b *BeaconNode) registerRPCService() error {
|
||||
EnableDebugRPCEndpoints: enableDebugRPCEndpoints,
|
||||
MaxMsgSize: maxMsgSize,
|
||||
ExecutionEngineCaller: web3Service.EngineAPIClient(),
|
||||
ProposerIdsCache: b.proposerIdsCache,
|
||||
})
|
||||
|
||||
return b.services.RegisterService(rpcService)
|
||||
|
||||
@@ -32,6 +32,14 @@ func WithHttpEndpoints(endpointStrings []string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithExecutionEndpoint for the execution node JSON-RPC endpoint.
|
||||
func WithExecutionEndpoint(endpoint string) Option {
|
||||
return func(s *Service) error {
|
||||
s.cfg.executionEndpoint = endpoint
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithExecutionClientJWTSecret for authenticating the execution node JSON-RPC endpoint.
|
||||
func WithExecutionClientJWTSecret(jwtSecret []byte) Option {
|
||||
return func(s *Service) error {
|
||||
|
||||
@@ -135,6 +135,7 @@ type config struct {
|
||||
eth1HeaderReqLimit uint64
|
||||
beaconNodeStatsUpdater BeaconNodeStatsUpdater
|
||||
httpEndpoints []network.Endpoint
|
||||
executionEndpoint string
|
||||
executionEndpointJWTSecret []byte
|
||||
currHttpEndpoint network.Endpoint
|
||||
finalizedStateAtStartup state.BeaconState
|
||||
@@ -212,6 +213,13 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.initializeEngineAPIClient(ctx); err != nil {
|
||||
return nil, errors.Wrap(err, "unable to initialize engine API client")
|
||||
}
|
||||
|
||||
// Check transition configuration for the engine API client in the background.
|
||||
go s.checkTransitionConfiguration(ctx)
|
||||
|
||||
if err := s.ensureValidPowchainData(ctx); err != nil {
|
||||
return nil, errors.Wrap(err, "unable to validate powchain data")
|
||||
}
|
||||
@@ -247,13 +255,6 @@ func (s *Service) Start() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.initializeEngineAPIClient(s.ctx); err != nil {
|
||||
log.WithError(err).Fatal("unable to initialize engine API client")
|
||||
}
|
||||
|
||||
// Check transition configuration for the engine API client in the background.
|
||||
go s.checkTransitionConfiguration(s.ctx)
|
||||
|
||||
go func() {
|
||||
s.isRunning = true
|
||||
s.waitForConnection()
|
||||
@@ -1056,12 +1057,15 @@ func (s *Service) ensureValidPowchainData(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Initializes a connection to the engine API if an execution provider endpoint is set.
|
||||
// Initializes a client for the engine API if an execution provider endpoint is set.
|
||||
func (s *Service) initializeEngineAPIClient(ctx context.Context) error {
|
||||
if s.cfg.executionEndpoint == "" {
|
||||
return nil
|
||||
}
|
||||
opts := []engine.Option{
|
||||
engine.WithJWTSecret(s.cfg.executionEndpointJWTSecret),
|
||||
}
|
||||
client, err := engine.New(ctx, s.cfg.currHttpEndpoint.Url, opts...)
|
||||
client, err := engine.New(ctx, s.cfg.executionEndpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -80,6 +80,8 @@ go_library(
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
"@com_github_holiman_uint256//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
|
||||
@@ -138,7 +138,7 @@ func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.
|
||||
return nil, status.Errorf(codes.Internal, "Could not compute committee assignments: %v", err)
|
||||
}
|
||||
// Query the next epoch assignments for committee subnet subscriptions.
|
||||
nextCommitteeAssignments, _, err := helpers.CommitteeAssignments(ctx, s, req.Epoch+1)
|
||||
nextCommitteeAssignments, nextProposerIndexToSlots, err := helpers.CommitteeAssignments(ctx, s, req.Epoch+1)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not compute next committee assignments: %v", err)
|
||||
}
|
||||
@@ -180,6 +180,12 @@ func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.
|
||||
nextAssignment.AttesterSlot = ca.AttesterSlot
|
||||
nextAssignment.CommitteeIndex = ca.CommitteeIndex
|
||||
}
|
||||
for _, slot := range proposerIndexToSlots[idx] {
|
||||
vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, idx, 0)
|
||||
}
|
||||
for _, slot := range nextProposerIndexToSlots[idx] {
|
||||
vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(slot, idx, 0)
|
||||
}
|
||||
} else {
|
||||
// If the validator isn't in the beacon state, try finding their deposit to determine their status.
|
||||
vStatus, _ := vs.validatorStatus(ctx, s, pubKey)
|
||||
|
||||
@@ -7,13 +7,13 @@ import (
|
||||
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/time"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
@@ -148,14 +148,18 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation
|
||||
ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestation")
|
||||
defer span.End()
|
||||
|
||||
if _, err := bls.SignatureFromBytes(att.Signature); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature")
|
||||
}
|
||||
|
||||
root, err := att.Data.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err)
|
||||
}
|
||||
hs, err := vs.HeadFetcher.HeadState(context.Background())
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not retrieve head state: %v", err)
|
||||
}
|
||||
if err := blocks.VerifyAttestationSignature(context.Background(), hs, att); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not verify attestation: %v. committee index of %d, slot %d, block root %#x ,target epoch %d , root %#x source epoch %d, root %#x had a bad signature %#x",
|
||||
err, att.Data.CommitteeIndex, att.Data.Slot, att.Data.BeaconBlockRoot, att.Data.Target.Epoch, att.Data.Target.Root, att.Data.Source.Epoch, att.Data.Source.Root, att.Signature)
|
||||
}
|
||||
|
||||
// Broadcast the unaggregated attestation on a feed to notify other services in the beacon node
|
||||
// of a received unaggregated attestation.
|
||||
|
||||
@@ -96,7 +96,17 @@ func (a proposerAtts) filter(ctx context.Context, st state.BeaconState) (propose
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return altair.ProcessAttestationNoVerifySignature(ctx, st, attestation, totalBalance)
|
||||
_, err = altair.ProcessAttestationNoVerifySignature(ctx, st, attestation, totalBalance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = blocks.VerifyAttestationSignature(ctx, st, attestation)
|
||||
if err != nil {
|
||||
log.Errorf("attestation with committee index of %d, slot %d, block root %#x ,target epoch %d , root %#x source epoch %d, root %#x had a bad signature %#x", attestation.Data.CommitteeIndex, attestation.Data.Slot,
|
||||
attestation.Data.BeaconBlockRoot, attestation.Data.Target.Epoch, attestation.Data.Target.Root, attestation.Data.Source.Epoch, attestation.Data.Source.Root, attestation.Signature)
|
||||
return nil, err
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
default:
|
||||
// Exit early if there is an unknown state type.
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
@@ -24,9 +26,31 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
// payloadIDCacheMiss tracks the number of payload ID requests that aren't present in the cache.
|
||||
payloadIDCacheMiss = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "payload_id_cache_miss",
|
||||
Help: "The number of payload id get requests that aren't present in the cache.",
|
||||
})
|
||||
// payloadIDCacheHit tracks the number of payload ID requests that are present in the cache.
|
||||
payloadIDCacheHit = promauto.NewCounter(prometheus.CounterOpts{
|
||||
Name: "payload_id_cache_hit",
|
||||
Help: "The number of payload id get requests that are present in the cache.",
|
||||
})
|
||||
)
|
||||
|
||||
// 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) (*enginev1.ExecutionPayload, error) {
|
||||
vId, payloadId, ok := vs.ProposerSlotIndexCache.GetProposerPayloadIDs(slot)
|
||||
if ok && vId == vIdx && payloadId != 0 {
|
||||
var vIdBytes [8]byte
|
||||
copy(vIdBytes[:], bytesutil.Uint64ToBytesBigEndian(payloadId))
|
||||
payloadIDCacheHit.Inc()
|
||||
return vs.ExecutionEngineCaller.GetPayload(ctx, vIdBytes)
|
||||
}
|
||||
payloadIDCacheMiss.Inc()
|
||||
|
||||
st, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -38,7 +62,7 @@ func (vs *Server) getExecutionPayload(ctx context.Context, slot types.Slot, vIdx
|
||||
|
||||
var parentHash []byte
|
||||
var hasTerminalBlock bool
|
||||
mergeComplete, err := blocks.MergeTransitionComplete(st)
|
||||
mergeComplete, err := blocks.IsMergeTransitionComplete(st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/holiman/uint256"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain/engine-api-client/v1/mocks"
|
||||
powtesting "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||
@@ -107,6 +108,11 @@ func TestServer_getExecutionPayload(t *testing.T) {
|
||||
payloadID: &pb.PayloadIDBytes{0x1},
|
||||
validatorIndx: 1,
|
||||
},
|
||||
{
|
||||
name: "transition completed, happy case, payload ID cached)",
|
||||
st: transitionSt,
|
||||
validatorIndx: 100,
|
||||
},
|
||||
{
|
||||
name: "transition completed, could not prepare payload",
|
||||
st: transitionSt,
|
||||
@@ -133,10 +139,12 @@ func TestServer_getExecutionPayload(t *testing.T) {
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
vs := &Server{
|
||||
ExecutionEngineCaller: &mocks.EngineClient{PayloadIDBytes: tt.payloadID, ErrForkchoiceUpdated: tt.forkchoiceErr},
|
||||
HeadFetcher: &chainMock.ChainService{State: tt.st},
|
||||
BeaconDB: beaconDB,
|
||||
ExecutionEngineCaller: &mocks.EngineClient{PayloadIDBytes: tt.payloadID, ErrForkchoiceUpdated: tt.forkchoiceErr},
|
||||
HeadFetcher: &chainMock.ChainService{State: tt.st},
|
||||
BeaconDB: beaconDB,
|
||||
ProposerSlotIndexCache: cache.NewProposerPayloadIDsCache(),
|
||||
}
|
||||
vs.ProposerSlotIndexCache.SetProposerAndPayloadIDs(tt.st.Slot(), 100, 100)
|
||||
_, err := vs.getExecutionPayload(context.Background(), tt.st.Slot(), tt.validatorIndx)
|
||||
if tt.errString != "" {
|
||||
require.ErrorContains(t, tt.errString, err)
|
||||
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
type Server struct {
|
||||
Ctx context.Context
|
||||
AttestationCache *cache.AttestationCache
|
||||
ProposerSlotIndexCache *cache.ProposerPayloadIDsCache
|
||||
HeadFetcher blockchain.HeadFetcher
|
||||
ForkFetcher blockchain.ForkFetcher
|
||||
FinalizationFetcher blockchain.FinalizationFetcher
|
||||
|
||||
@@ -110,6 +110,7 @@ type Config struct {
|
||||
StateGen *stategen.State
|
||||
MaxMsgSize int
|
||||
ExecutionEngineCaller enginev1.Caller
|
||||
ProposerIdsCache *cache.ProposerPayloadIDsCache
|
||||
}
|
||||
|
||||
// NewService instantiates a new RPC service instance that will
|
||||
@@ -208,6 +209,7 @@ func (s *Service) Start() {
|
||||
ReplayerBuilder: ch,
|
||||
ExecutionEngineCaller: s.cfg.ExecutionEngineCaller,
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
ProposerSlotIndexCache: s.cfg.ProposerIdsCache,
|
||||
}
|
||||
validatorServerV1 := &validator.Server{
|
||||
HeadFetcher: s.cfg.HeadFetcher,
|
||||
|
||||
@@ -31,6 +31,9 @@ const (
|
||||
lookaheadSteps = 8
|
||||
// noRequiredPeersErrMaxRetries defines number of retries when no required peers are found.
|
||||
noRequiredPeersErrMaxRetries = 1000
|
||||
// noRequiredPeersErrMinReadjustment defines number of retries when no required peers are found
|
||||
// for thoe node to readjust the highest expected slot.
|
||||
noRequiredPeersErrMinReadjustment = 50
|
||||
// noRequiredPeersErrRefreshInterval defines interval for which queue will be paused before
|
||||
// making the next attempt to obtain data.
|
||||
noRequiredPeersErrRefreshInterval = 15 * time.Second
|
||||
@@ -232,6 +235,12 @@ func (q *blocksQueue) loop() {
|
||||
} else {
|
||||
q.exitConditions.noRequiredPeersErrRetries++
|
||||
log.Debug("Waiting for finalized peers")
|
||||
// Re-adjust highest expected slot, in the event we
|
||||
// cannot find the appropriate number of peers to sync with.
|
||||
if q.exitConditions.noRequiredPeersErrRetries > noRequiredPeersErrMinReadjustment &&
|
||||
q.highestExpectedSlot > q.blocksFetcher.bestNonFinalizedSlot() {
|
||||
q.highestExpectedSlot = q.blocksFetcher.bestNonFinalizedSlot()
|
||||
}
|
||||
time.Sleep(noRequiredPeersErrRefreshInterval)
|
||||
}
|
||||
continue
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/monitoring/tracing"
|
||||
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
|
||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||
prysmTime "github.com/prysmaticlabs/prysm/time"
|
||||
"github.com/prysmaticlabs/prysm/time/slots"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -167,11 +166,11 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
|
||||
err = s.validateBeaconBlock(ctx, blk, blockRoot)
|
||||
if err != nil {
|
||||
// If the parent is optimistic, be gracious and don't penalize the peer.
|
||||
if errors.Is(ErrOptimisticParent, err) {
|
||||
return pubsub.ValidationIgnore, err
|
||||
// If the parent is optimistic, process the block as usual
|
||||
// This also does not penalize a peer which sends optimistic blocks
|
||||
if !errors.Is(ErrOptimisticParent, err) {
|
||||
return pubsub.ValidationReject, err
|
||||
}
|
||||
return pubsub.ValidationReject, err
|
||||
}
|
||||
|
||||
// Record attribute of valid block.
|
||||
@@ -258,12 +257,9 @@ func (s *Service) validateBellatrixBeaconBlock(ctx context.Context, parentState
|
||||
if parentState.Version() != blk.Version() {
|
||||
return errors.New("block and state are not the same version")
|
||||
}
|
||||
if parentState.Version() != version.Bellatrix || blk.Version() != version.Bellatrix {
|
||||
return nil
|
||||
}
|
||||
|
||||
body := blk.Body()
|
||||
executionEnabled, err := blocks.ExecutionEnabled(parentState, body)
|
||||
executionEnabled, err := blocks.IsExecutionEnabled(parentState, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,6 +17,12 @@ var (
|
||||
Usage: "A mainchain web3 provider string http endpoint. Can contain auth header as well in the format --http-web3provider=\"https://goerli.infura.io/v3/xxxx,Basic xxx\" for project secret (base64 encoded) and --http-web3provider=\"https://goerli.infura.io/v3/xxxx,Bearer xxx\" for jwt use",
|
||||
Value: "",
|
||||
}
|
||||
// ExecutionProvider provides an HTTP or IPC access endpoint to an ETH execution node.
|
||||
ExecutionProviderFlag = &cli.StringFlag{
|
||||
Name: "execution-provider",
|
||||
Usage: "An http endpoint for an Ethereum execution node",
|
||||
Value: "",
|
||||
}
|
||||
// ExecutionJWTSecretFlag provides a path to a file containing a hex-encoded string representing a 32 byte secret
|
||||
// used to authenticate with an execution node via HTTP. This is required if using an HTTP connection, otherwise all requests
|
||||
// to execution nodes for consensus-related calls will fail. This is not required if using an IPC connection.
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
var appFlags = []cli.Flag{
|
||||
flags.DepositContractFlag,
|
||||
flags.HTTPWeb3ProviderFlag,
|
||||
flags.ExecutionProviderFlag,
|
||||
flags.ExecutionJWTSecretFlag,
|
||||
flags.FallbackWeb3ProviderFlag,
|
||||
flags.RPCHost,
|
||||
|
||||
@@ -18,6 +18,7 @@ var log = logrus.WithField("prefix", "cmd-powchain")
|
||||
// FlagOptions for powchain service flag configurations.
|
||||
func FlagOptions(c *cli.Context) ([]powchain.Option, error) {
|
||||
endpoints := parsePowchainEndpoints(c)
|
||||
executionEndpoint := parseExecutionEndpoint(c)
|
||||
jwtSecret, err := parseJWTSecretFromFile(c)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read JWT secret file for authenticating execution API")
|
||||
@@ -26,6 +27,9 @@ func FlagOptions(c *cli.Context) ([]powchain.Option, error) {
|
||||
powchain.WithHttpEndpoints(endpoints),
|
||||
powchain.WithEth1HeaderRequestLimit(c.Uint64(flags.Eth1HeaderReqLimit.Name)),
|
||||
}
|
||||
if executionEndpoint != "" {
|
||||
opts = append(opts, powchain.WithExecutionEndpoint(executionEndpoint))
|
||||
}
|
||||
if len(jwtSecret) > 0 {
|
||||
opts = append(opts, powchain.WithExecutionClientJWTSecret(jwtSecret))
|
||||
}
|
||||
@@ -81,3 +85,7 @@ func parsePowchainEndpoints(c *cli.Context) []string {
|
||||
endpoints = append(endpoints, c.StringSlice(flags.FallbackWeb3ProviderFlag.Name)...)
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func parseExecutionEndpoint(c *cli.Context) string {
|
||||
return c.String(flags.ExecutionProviderFlag.Name)
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.GRPCGatewayPort,
|
||||
flags.GPRCGatewayCorsDomain,
|
||||
flags.HTTPWeb3ProviderFlag,
|
||||
flags.ExecutionProviderFlag,
|
||||
flags.ExecutionJWTSecretFlag,
|
||||
flags.FallbackWeb3ProviderFlag,
|
||||
flags.SetGCPercent,
|
||||
|
||||
@@ -7,6 +7,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrUnsupportedField is returned when a field is not supported by a specific beacon block type.
|
||||
// This allows us to create a generic beacon block interface that is implemented by different
|
||||
// fork versions of beacon blocks.
|
||||
ErrUnsupportedField = errors.New("unsupported field for block type")
|
||||
// ErrUnsupportedSignedBeaconBlock is returned when the struct type is not a supported signed
|
||||
// beacon block type.
|
||||
ErrUnsupportedSignedBeaconBlock = errors.New("unsupported signed beacon block")
|
||||
|
||||
@@ -305,6 +305,6 @@ func (w altairBeaconBlockBody) Proto() proto.Message {
|
||||
}
|
||||
|
||||
// ExecutionPayload is a stub.
|
||||
func (altairBeaconBlockBody) ExecutionPayload() (*enginev1.ExecutionPayload, error) {
|
||||
return nil, errors.New("ExecutionPayload is not supported in altair block body")
|
||||
func (w altairBeaconBlockBody) ExecutionPayload() (*enginev1.ExecutionPayload, error) {
|
||||
return nil, errors.Wrapf(ErrUnsupportedField, "ExecutionPayload for %T", w)
|
||||
}
|
||||
|
||||
@@ -293,6 +293,6 @@ func (w Phase0BeaconBlockBody) Proto() proto.Message {
|
||||
}
|
||||
|
||||
// ExecutionPayload is a stub.
|
||||
func (Phase0BeaconBlockBody) ExecutionPayload() (*enginev1.ExecutionPayload, error) {
|
||||
return nil, errors.New("ExecutionPayload is not supported in phase 0 block body")
|
||||
func (w Phase0BeaconBlockBody) ExecutionPayload() (*enginev1.ExecutionPayload, error) {
|
||||
return nil, errors.Wrapf(ErrUnsupportedField, "ExecutionPayload for %T", w)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user