mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
Simplify fcu 2 (#13400)
* change getPayloadAttribute signature * Unify different FCU arguments
This commit is contained in:
parent
886d76fe7c
commit
8c1e180dd1
@ -32,22 +32,18 @@ const blobCommitmentVersionKZG uint8 = 0x01
|
|||||||
|
|
||||||
var defaultLatestValidHash = bytesutil.PadTo([]byte{0xff}, 32)
|
var defaultLatestValidHash = bytesutil.PadTo([]byte{0xff}, 32)
|
||||||
|
|
||||||
// notifyForkchoiceUpdateArg is the argument for the forkchoice update notification `notifyForkchoiceUpdate`.
|
|
||||||
type notifyForkchoiceUpdateArg struct {
|
|
||||||
headState state.BeaconState
|
|
||||||
headRoot [32]byte
|
|
||||||
headBlock interfaces.ReadOnlyBeaconBlock
|
|
||||||
attributes payloadattribute.Attributer
|
|
||||||
}
|
|
||||||
|
|
||||||
// notifyForkchoiceUpdate signals execution engine the fork choice updates. Execution engine should:
|
// 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.
|
// 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.
|
// 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.
|
||||||
func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkchoiceUpdateArg) (*enginev1.PayloadIDBytes, error) {
|
func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *fcuConfig) (*enginev1.PayloadIDBytes, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "blockChain.notifyForkchoiceUpdate")
|
ctx, span := trace.StartSpan(ctx, "blockChain.notifyForkchoiceUpdate")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
headBlk := arg.headBlock
|
if arg.headBlock.IsNil() {
|
||||||
|
log.Error("Head block is nil")
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
headBlk := arg.headBlock.Block()
|
||||||
if headBlk == nil || headBlk.IsNil() || headBlk.Body().IsNil() {
|
if headBlk == nil || headBlk.IsNil() || headBlk.Body().IsNil() {
|
||||||
log.Error("Head block is nil")
|
log.Error("Head block is nil")
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -122,10 +118,10 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *notifyForkcho
|
|||||||
log.WithError(err).Error("Could not get head state")
|
log.WithError(err).Error("Could not get head state")
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
pid, err := s.notifyForkchoiceUpdate(ctx, ¬ifyForkchoiceUpdateArg{
|
pid, err := s.notifyForkchoiceUpdate(ctx, &fcuConfig{
|
||||||
headState: st,
|
headState: st,
|
||||||
headRoot: r,
|
headRoot: r,
|
||||||
headBlock: b.Block(),
|
headBlock: b,
|
||||||
attributes: arg.attributes,
|
attributes: arg.attributes,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -280,7 +276,7 @@ func (s *Service) pruneInvalidBlock(ctx context.Context, root, parentRoot, lvh [
|
|||||||
|
|
||||||
// getPayloadAttributes returns the payload attributes for the given state and slot.
|
// getPayloadAttributes 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_forkchoiceUpdated` call.
|
// The attribute is required to initiate a payload build process in the context of an `engine_forkchoiceUpdated` call.
|
||||||
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot primitives.Slot, headRoot []byte) (bool, payloadattribute.Attributer) {
|
func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, slot primitives.Slot, headRoot []byte) payloadattribute.Attributer {
|
||||||
emptyAttri := payloadattribute.EmptyWithVersion(st.Version())
|
emptyAttri := payloadattribute.EmptyWithVersion(st.Version())
|
||||||
|
|
||||||
// If it is an epoch boundary then process slots to get the right
|
// If it is an epoch boundary then process slots to get the right
|
||||||
@ -293,7 +289,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
|||||||
if e == stateEpoch {
|
if e == stateEpoch {
|
||||||
val, ok = s.trackedProposer(st, slot)
|
val, ok = s.trackedProposer(st, slot)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st = st.Copy()
|
st = st.Copy()
|
||||||
@ -302,27 +298,28 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
|||||||
st, err = transition.ProcessSlotsUsingNextSlotCache(ctx, st, headRoot, slot)
|
st, err = transition.ProcessSlotsUsingNextSlotCache(ctx, st, headRoot, slot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not process slots to get payload attribute")
|
log.WithError(err).Error("Could not process slots to get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if e > stateEpoch {
|
if e > stateEpoch {
|
||||||
|
emptyAttri := payloadattribute.EmptyWithVersion(st.Version())
|
||||||
val, ok = s.trackedProposer(st, slot)
|
val, ok = s.trackedProposer(st, slot)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get previous randao.
|
// Get previous randao.
|
||||||
prevRando, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
|
prevRando, err := helpers.RandaoMix(st, time.CurrentEpoch(st))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not get randao mix to get payload attribute")
|
log.WithError(err).Error("Could not get randao mix to get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get timestamp.
|
// Get timestamp.
|
||||||
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
|
t, err := slots.ToTime(uint64(s.genesisTime.Unix()), slot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not get timestamp to get payload attribute")
|
log.WithError(err).Error("Could not get timestamp to get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
|
|
||||||
var attr payloadattribute.Attributer
|
var attr payloadattribute.Attributer
|
||||||
@ -331,7 +328,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
|||||||
withdrawals, err := st.ExpectedWithdrawals()
|
withdrawals, err := st.ExpectedWithdrawals()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
|
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV3{
|
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV3{
|
||||||
Timestamp: uint64(t.Unix()),
|
Timestamp: uint64(t.Unix()),
|
||||||
@ -342,13 +339,13 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not get payload attribute")
|
log.WithError(err).Error("Could not get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
case version.Capella:
|
case version.Capella:
|
||||||
withdrawals, err := st.ExpectedWithdrawals()
|
withdrawals, err := st.ExpectedWithdrawals()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
|
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
|
attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{
|
||||||
Timestamp: uint64(t.Unix()),
|
Timestamp: uint64(t.Unix()),
|
||||||
@ -358,7 +355,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not get payload attribute")
|
log.WithError(err).Error("Could not get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
case version.Bellatrix:
|
case version.Bellatrix:
|
||||||
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
|
attr, err = payloadattribute.New(&enginev1.PayloadAttributes{
|
||||||
@ -368,14 +365,14 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Could not get payload attribute")
|
log.WithError(err).Error("Could not get payload attribute")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.WithField("version", st.Version()).Error("Could not get payload attribute due to unknown state version")
|
log.WithField("version", st.Version()).Error("Could not get payload attribute due to unknown state version")
|
||||||
return false, emptyAttri
|
return emptyAttri
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, attr
|
return attr
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeInvalidBlockAndState removes the invalid block, blob and its corresponding state from the cache and DB.
|
// removeInvalidBlockAndState removes the invalid block, blob and its corresponding state from the cache and DB.
|
||||||
|
@ -56,11 +56,14 @@ func Test_NotifyForkchoiceUpdate_GetPayloadAttrErrorCanContinue(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, fcs.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, fcs.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlockBellatrix{
|
sb := ðpb.SignedBeaconBlockBellatrix{
|
||||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
Block: ðpb.BeaconBlockBellatrix{
|
||||||
ExecutionPayload: &v1.ExecutionPayload{},
|
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||||
|
ExecutionPayload: &v1.ExecutionPayload{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
b, err := consensusblocks.NewSignedBeaconBlock(sb)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pid := &v1.PayloadIDBytes{1}
|
pid := &v1.PayloadIDBytes{1}
|
||||||
@ -72,7 +75,7 @@ func Test_NotifyForkchoiceUpdate_GetPayloadAttrErrorCanContinue(t *testing.T) {
|
|||||||
// Intentionally generate a bad state such that `hash_tree_root` fails during `process_slot`
|
// Intentionally generate a bad state such that `hash_tree_root` fails during `process_slot`
|
||||||
s, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{})
|
s, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
arg := ¬ifyForkchoiceUpdateArg{
|
arg := &fcuConfig{
|
||||||
headState: s,
|
headState: s,
|
||||||
headRoot: [32]byte{},
|
headRoot: [32]byte{},
|
||||||
headBlock: b,
|
headBlock: b,
|
||||||
@ -113,7 +116,7 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
blk interfaces.ReadOnlyBeaconBlock
|
blk interfaces.ReadOnlySignedBeaconBlock
|
||||||
headRoot [32]byte
|
headRoot [32]byte
|
||||||
finalizedRoot [32]byte
|
finalizedRoot [32]byte
|
||||||
justifiedRoot [32]byte
|
justifiedRoot [32]byte
|
||||||
@ -122,24 +125,24 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "phase0 block",
|
name: "phase0 block",
|
||||||
blk: func() interfaces.ReadOnlyBeaconBlock {
|
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}})
|
b, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{}}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}(),
|
}(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "altair block",
|
name: "altair block",
|
||||||
blk: func() interfaces.ReadOnlyBeaconBlock {
|
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlockAltair{Body: ðpb.BeaconBlockBodyAltair{}})
|
b, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockAltair{Block: ðpb.BeaconBlockAltair{Body: ðpb.BeaconBlockBodyAltair{}}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}(),
|
}(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not execution block",
|
name: "not execution block",
|
||||||
blk: func() interfaces.ReadOnlyBeaconBlock {
|
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlockBellatrix{
|
b, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: ðpb.BeaconBlockBellatrix{
|
||||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||||
ExecutionPayload: &v1.ExecutionPayload{
|
ExecutionPayload: &v1.ExecutionPayload{
|
||||||
ParentHash: make([]byte, fieldparams.RootLength),
|
ParentHash: make([]byte, fieldparams.RootLength),
|
||||||
@ -152,19 +155,19 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
BlockHash: make([]byte, fieldparams.RootLength),
|
BlockHash: make([]byte, fieldparams.RootLength),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}(),
|
}(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "happy case: finalized root is altair block",
|
name: "happy case: finalized root is altair block",
|
||||||
blk: func() interfaces.ReadOnlyBeaconBlock {
|
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlockBellatrix{
|
b, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: ðpb.BeaconBlockBellatrix{
|
||||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||||
ExecutionPayload: &v1.ExecutionPayload{},
|
ExecutionPayload: &v1.ExecutionPayload{},
|
||||||
},
|
},
|
||||||
})
|
}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}(),
|
}(),
|
||||||
@ -173,12 +176,12 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "happy case: finalized root is bellatrix block",
|
name: "happy case: finalized root is bellatrix block",
|
||||||
blk: func() interfaces.ReadOnlyBeaconBlock {
|
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlockBellatrix{
|
b, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: ðpb.BeaconBlockBellatrix{
|
||||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||||
ExecutionPayload: &v1.ExecutionPayload{},
|
ExecutionPayload: &v1.ExecutionPayload{},
|
||||||
},
|
},
|
||||||
})
|
}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}(),
|
}(),
|
||||||
@ -187,12 +190,12 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "forkchoice updated with optimistic block",
|
name: "forkchoice updated with optimistic block",
|
||||||
blk: func() interfaces.ReadOnlyBeaconBlock {
|
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlockBellatrix{
|
b, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: ðpb.BeaconBlockBellatrix{
|
||||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||||
ExecutionPayload: &v1.ExecutionPayload{},
|
ExecutionPayload: &v1.ExecutionPayload{},
|
||||||
},
|
},
|
||||||
})
|
}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}(),
|
}(),
|
||||||
@ -202,12 +205,12 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "forkchoice updated with invalid block",
|
name: "forkchoice updated with invalid block",
|
||||||
blk: func() interfaces.ReadOnlyBeaconBlock {
|
blk: func() interfaces.ReadOnlySignedBeaconBlock {
|
||||||
b, err := consensusblocks.NewBeaconBlock(ðpb.BeaconBlockBellatrix{
|
b, err := consensusblocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: ðpb.BeaconBlockBellatrix{
|
||||||
Body: ðpb.BeaconBlockBodyBellatrix{
|
Body: ðpb.BeaconBlockBodyBellatrix{
|
||||||
ExecutionPayload: &v1.ExecutionPayload{},
|
ExecutionPayload: &v1.ExecutionPayload{},
|
||||||
},
|
},
|
||||||
})
|
}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}(),
|
}(),
|
||||||
@ -225,7 +228,7 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
st, _ := util.DeterministicGenesisState(t, 1)
|
st, _ := util.DeterministicGenesisState(t, 1)
|
||||||
require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot))
|
require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot))
|
||||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot))
|
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot))
|
||||||
arg := ¬ifyForkchoiceUpdateArg{
|
arg := &fcuConfig{
|
||||||
headState: st,
|
headState: st,
|
||||||
headRoot: tt.headRoot,
|
headRoot: tt.headRoot,
|
||||||
headBlock: tt.blk,
|
headBlock: tt.blk,
|
||||||
@ -305,9 +308,9 @@ func Test_NotifyForkchoiceUpdate_NIlLVH(t *testing.T) {
|
|||||||
|
|
||||||
require.NoError(t, beaconDB.SaveState(ctx, st, bra))
|
require.NoError(t, beaconDB.SaveState(ctx, st, bra))
|
||||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra))
|
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra))
|
||||||
a := ¬ifyForkchoiceUpdateArg{
|
a := &fcuConfig{
|
||||||
headState: st,
|
headState: st,
|
||||||
headBlock: wbd.Block(),
|
headBlock: wbd,
|
||||||
headRoot: brd,
|
headRoot: brd,
|
||||||
}
|
}
|
||||||
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
||||||
@ -442,9 +445,9 @@ func Test_NotifyForkchoiceUpdateRecursive_DoublyLinkedTree(t *testing.T) {
|
|||||||
|
|
||||||
require.NoError(t, beaconDB.SaveState(ctx, st, bra))
|
require.NoError(t, beaconDB.SaveState(ctx, st, bra))
|
||||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra))
|
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra))
|
||||||
a := ¬ifyForkchoiceUpdateArg{
|
a := &fcuConfig{
|
||||||
headState: st,
|
headState: st,
|
||||||
headBlock: wbg.Block(),
|
headBlock: wbg,
|
||||||
headRoot: brg,
|
headRoot: brg,
|
||||||
}
|
}
|
||||||
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
||||||
@ -780,23 +783,23 @@ func Test_GetPayloadAttribute(t *testing.T) {
|
|||||||
ctx := tr.ctx
|
ctx := tr.ctx
|
||||||
|
|
||||||
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
|
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
|
||||||
hasPayload, _ := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
attr := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
||||||
require.Equal(t, false, hasPayload)
|
require.Equal(t, true, attr.IsEmpty())
|
||||||
|
|
||||||
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
|
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
|
||||||
// Cache hit, advance state, no fee recipient
|
// Cache hit, advance state, no fee recipient
|
||||||
slot := primitives.Slot(1)
|
slot := primitives.Slot(1)
|
||||||
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
||||||
hasPayload, attr := service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
||||||
require.Equal(t, true, hasPayload)
|
require.Equal(t, false, attr.IsEmpty())
|
||||||
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
||||||
|
|
||||||
// Cache hit, advance state, has fee recipient
|
// Cache hit, advance state, has fee recipient
|
||||||
suggestedAddr := common.HexToAddress("123")
|
suggestedAddr := common.HexToAddress("123")
|
||||||
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
|
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
|
||||||
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
||||||
hasPayload, attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
||||||
require.Equal(t, true, hasPayload)
|
require.Equal(t, false, attr.IsEmpty())
|
||||||
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
|
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -810,8 +813,8 @@ func Test_GetPayloadAttribute_PrepareAllPayloads(t *testing.T) {
|
|||||||
ctx := tr.ctx
|
ctx := tr.ctx
|
||||||
|
|
||||||
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
|
st, _ := util.DeterministicGenesisStateBellatrix(t, 1)
|
||||||
hasPayload, attr := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
attr := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
||||||
require.Equal(t, true, hasPayload)
|
require.Equal(t, false, attr.IsEmpty())
|
||||||
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,15 +823,15 @@ func Test_GetPayloadAttributeV2(t *testing.T) {
|
|||||||
ctx := tr.ctx
|
ctx := tr.ctx
|
||||||
|
|
||||||
st, _ := util.DeterministicGenesisStateCapella(t, 1)
|
st, _ := util.DeterministicGenesisStateCapella(t, 1)
|
||||||
hasPayload, _ := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
attr := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
||||||
require.Equal(t, false, hasPayload)
|
require.Equal(t, true, attr.IsEmpty())
|
||||||
|
|
||||||
// Cache hit, advance state, no fee recipient
|
// Cache hit, advance state, no fee recipient
|
||||||
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
|
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
|
||||||
slot := primitives.Slot(1)
|
slot := primitives.Slot(1)
|
||||||
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
||||||
hasPayload, attr := service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
||||||
require.Equal(t, true, hasPayload)
|
require.Equal(t, false, attr.IsEmpty())
|
||||||
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
||||||
a, err := attr.Withdrawals()
|
a, err := attr.Withdrawals()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -838,8 +841,8 @@ func Test_GetPayloadAttributeV2(t *testing.T) {
|
|||||||
suggestedAddr := common.HexToAddress("123")
|
suggestedAddr := common.HexToAddress("123")
|
||||||
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
|
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
|
||||||
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
||||||
hasPayload, attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
||||||
require.Equal(t, true, hasPayload)
|
require.Equal(t, false, attr.IsEmpty())
|
||||||
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
|
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
|
||||||
a, err = attr.Withdrawals()
|
a, err = attr.Withdrawals()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -851,15 +854,15 @@ func Test_GetPayloadAttributeDeneb(t *testing.T) {
|
|||||||
ctx := tr.ctx
|
ctx := tr.ctx
|
||||||
|
|
||||||
st, _ := util.DeterministicGenesisStateDeneb(t, 1)
|
st, _ := util.DeterministicGenesisStateDeneb(t, 1)
|
||||||
hasPayload, _ := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
attr := service.getPayloadAttribute(ctx, st, 0, []byte{})
|
||||||
require.Equal(t, false, hasPayload)
|
require.Equal(t, true, attr.IsEmpty())
|
||||||
|
|
||||||
// Cache hit, advance state, no fee recipient
|
// Cache hit, advance state, no fee recipient
|
||||||
slot := primitives.Slot(1)
|
slot := primitives.Slot(1)
|
||||||
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
|
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
|
||||||
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
||||||
hasPayload, attr := service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
||||||
require.Equal(t, true, hasPayload)
|
require.Equal(t, false, attr.IsEmpty())
|
||||||
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
|
||||||
a, err := attr.Withdrawals()
|
a, err := attr.Withdrawals()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -869,8 +872,8 @@ func Test_GetPayloadAttributeDeneb(t *testing.T) {
|
|||||||
suggestedAddr := common.HexToAddress("123")
|
suggestedAddr := common.HexToAddress("123")
|
||||||
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
|
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
|
||||||
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
|
||||||
hasPayload, attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
|
||||||
require.Equal(t, true, hasPayload)
|
require.Equal(t, false, attr.IsEmpty())
|
||||||
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
|
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
|
||||||
a, err = attr.Withdrawals()
|
a, err = attr.Withdrawals()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/v4/config/features"
|
"github.com/prysmaticlabs/prysm/v4/config/features"
|
||||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
||||||
|
payloadattribute "github.com/prysmaticlabs/prysm/v4/consensus-types/payload-attribute"
|
||||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/v4/time/slots"
|
"github.com/prysmaticlabs/prysm/v4/time/slots"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -49,6 +50,7 @@ type fcuConfig struct {
|
|||||||
headBlock interfaces.ReadOnlySignedBeaconBlock
|
headBlock interfaces.ReadOnlySignedBeaconBlock
|
||||||
headRoot [32]byte
|
headRoot [32]byte
|
||||||
proposingSlot primitives.Slot
|
proposingSlot primitives.Slot
|
||||||
|
attributes payloadattribute.Attributer
|
||||||
}
|
}
|
||||||
|
|
||||||
// fockchoiceUpdateWithExecution is a wrapper around notifyForkchoiceUpdate. It decides whether a new call to FCU should be made.
|
// fockchoiceUpdateWithExecution is a wrapper around notifyForkchoiceUpdate. It decides whether a new call to FCU should be made.
|
||||||
@ -57,21 +59,17 @@ func (s *Service) forkchoiceUpdateWithExecution(ctx context.Context, args *fcuCo
|
|||||||
defer span.End()
|
defer span.End()
|
||||||
// Note: Use the service context here to avoid the parent context being ended during a forkchoice update.
|
// Note: Use the service context here to avoid the parent context being ended during a forkchoice update.
|
||||||
ctx = trace.NewContext(s.ctx, span)
|
ctx = trace.NewContext(s.ctx, span)
|
||||||
fcuArgs := ¬ifyForkchoiceUpdateArg{
|
fcuArgs := &fcuConfig{
|
||||||
headState: args.headState,
|
headState: args.headState,
|
||||||
headRoot: args.headRoot,
|
headRoot: args.headRoot,
|
||||||
headBlock: args.headBlock.Block(),
|
headBlock: args.headBlock,
|
||||||
}
|
}
|
||||||
_, tracked := s.trackedProposer(args.headState, args.proposingSlot)
|
_, tracked := s.trackedProposer(args.headState, args.proposingSlot)
|
||||||
if tracked && !features.Get().DisableReorgLateBlocks {
|
if tracked && !features.Get().DisableReorgLateBlocks {
|
||||||
if s.shouldOverrideFCU(args.headRoot, args.proposingSlot) {
|
if s.shouldOverrideFCU(args.headRoot, args.proposingSlot) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var has bool
|
fcuArgs.attributes = s.getPayloadAttribute(ctx, args.headState, args.proposingSlot, args.headRoot[:])
|
||||||
has, fcuArgs.attributes = s.getPayloadAttribute(ctx, args.headState, args.proposingSlot, args.headRoot[:])
|
|
||||||
if !has {
|
|
||||||
log.Error("could not get payload attributes for tracked proposer")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_, err := s.notifyForkchoiceUpdate(ctx, fcuArgs)
|
_, err := s.notifyForkchoiceUpdate(ctx, fcuArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -342,10 +342,10 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []consensusblocks.ROBlo
|
|||||||
return errors.Wrap(err, "could not set optimistic block to valid")
|
return errors.Wrap(err, "could not set optimistic block to valid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arg := ¬ifyForkchoiceUpdateArg{
|
arg := &fcuConfig{
|
||||||
headState: preState,
|
headState: preState,
|
||||||
headRoot: lastBR,
|
headRoot: lastBR,
|
||||||
headBlock: lastB.Block(),
|
headBlock: lastB,
|
||||||
}
|
}
|
||||||
if _, err := s.notifyForkchoiceUpdate(ctx, arg); err != nil {
|
if _, err := s.notifyForkchoiceUpdate(ctx, arg); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -711,12 +711,12 @@ func (s *Service) lateBlockTasks(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
s.headLock.RUnlock()
|
s.headLock.RUnlock()
|
||||||
s.cfg.ForkChoiceStore.RLock()
|
s.cfg.ForkChoiceStore.RLock()
|
||||||
fcuArgs := ¬ifyForkchoiceUpdateArg{
|
fcuArgs := &fcuConfig{
|
||||||
headState: headState,
|
headState: headState,
|
||||||
headRoot: headRoot,
|
headRoot: headRoot,
|
||||||
headBlock: headBlock.Block(),
|
headBlock: headBlock,
|
||||||
}
|
}
|
||||||
_, fcuArgs.attributes = s.getPayloadAttribute(ctx, headState, s.CurrentSlot()+1, headRoot[:])
|
fcuArgs.attributes = s.getPayloadAttribute(ctx, headState, s.CurrentSlot()+1, headRoot[:])
|
||||||
_, err = s.notifyForkchoiceUpdate(ctx, fcuArgs)
|
_, err = s.notifyForkchoiceUpdate(ctx, fcuArgs)
|
||||||
s.cfg.ForkChoiceStore.RUnlock()
|
s.cfg.ForkChoiceStore.RUnlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -16,6 +16,9 @@ import (
|
|||||||
// incoming objects. (24 mins with mainnet spec)
|
// incoming objects. (24 mins with mainnet spec)
|
||||||
const MaxSlotBuffer = uint64(1 << 7)
|
const MaxSlotBuffer = uint64(1 << 7)
|
||||||
|
|
||||||
|
// votingWindow specifies the deadline for attestations
|
||||||
|
var votingWindow = params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
|
||||||
|
|
||||||
// startFromTime returns the slot start in terms of genesis time.Time
|
// startFromTime returns the slot start in terms of genesis time.Time
|
||||||
func startFromTime(genesis time.Time, slot primitives.Slot) time.Time {
|
func startFromTime(genesis time.Time, slot primitives.Slot) time.Time {
|
||||||
duration := time.Second * time.Duration(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
duration := time.Second * time.Duration(slot.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||||
@ -264,3 +267,9 @@ func SecondsSinceSlotStart(s primitives.Slot, genesisTime, timeStamp uint64) (ui
|
|||||||
func TimeIntoSlot(genesisTime uint64) time.Duration {
|
func TimeIntoSlot(genesisTime uint64) time.Duration {
|
||||||
return time.Since(StartTime(genesisTime, CurrentSlot(genesisTime)))
|
return time.Since(StartTime(genesisTime, CurrentSlot(genesisTime)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithinVotingWindow returns whether the current time is within the voting window
|
||||||
|
// (eg. 4 seconds on mainnet) of the current slot.
|
||||||
|
func WithinVotingWindow(genesisTime uint64) bool {
|
||||||
|
return TimeIntoSlot(genesisTime) < time.Duration(votingWindow)*time.Second
|
||||||
|
}
|
||||||
|
@ -600,3 +600,10 @@ func TestTimeIntoSlot(t *testing.T) {
|
|||||||
require.Equal(t, true, TimeIntoSlot(genesisTime) > 900*time.Millisecond)
|
require.Equal(t, true, TimeIntoSlot(genesisTime) > 900*time.Millisecond)
|
||||||
require.Equal(t, true, TimeIntoSlot(genesisTime) < 3000*time.Millisecond)
|
require.Equal(t, true, TimeIntoSlot(genesisTime) < 3000*time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWithinVotingWindow(t *testing.T) {
|
||||||
|
genesisTime := uint64(time.Now().Add(-37 * time.Second).Unix())
|
||||||
|
require.Equal(t, true, WithinVotingWindow(genesisTime))
|
||||||
|
genesisTime = uint64(time.Now().Add(-40 * time.Second).Unix())
|
||||||
|
require.Equal(t, false, WithinVotingWindow(genesisTime))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user