New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better head
object coupling for chain service
#4869
Conversation
// This gets called to update canonical root mapping. It does not save head block | ||
// root in DB. With the inception of inital-sync-cache-state flag, it uses finalized | ||
// check point as anchors to resume sync therefore head is no longer needed to be saved on per slot basis. | ||
func (s *Service) saveHeadNoDB(ctx context.Context, b *ethpb.SignedBeaconBlock, r [32]byte) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is an old function, I moved it from service.go
to here, it makes more sense here
beacon-chain/blockchain/head.go
Outdated
} | ||
|
||
// This sets head view object which is used to track the head slot, root, block and state. | ||
func (s *Service) setHead(slot uint64, root [32]byte, block *ethpb.SignedBeaconBlock, state *state.BeaconState) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
start review here lines 145 to 205
const latestSlotCount = 10 | ||
|
||
// HeadsHandler is a handler to serve /heads page in metrics. | ||
func (s *Service) HeadsHandler(w http.ResponseWriter, _ *http.Request) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was not used at all. Removing it because it was too much work to maintain
beacon-chain/blockchain/head.go
Outdated
s.headLock.RLock() | ||
defer s.headLock.RUnlock() | ||
|
||
return !(s.head == nil) && !(s.head.state == nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return !(s.head == nil) && !(s.head.state == nil) | |
return s.head != nil && s.head.state != nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice :)
Codecov Report
@@ Coverage Diff @@
## master #4869 +/- ##
=========================================
Coverage ? 44.34%
=========================================
Files ? 203
Lines ? 15205
Branches ? 0
=========================================
Hits ? 6742
Misses ? 7382
Partials ? 1081 |
beacon-chain/blockchain/head.go
Outdated
} | ||
|
||
// This sets head view object which is used to track the head slot, root, block and state. | ||
func (s *Service) setHead(slot uint64, root [32]byte, block *ethpb.SignedBeaconBlock, state *state.BeaconState) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we dont need a slot param, cant we just get it from the block ?
beacon-chain/blockchain/head.go
Outdated
slot: slot, | ||
root: root, | ||
block: block, | ||
state: state, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please copy the state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also copied the block as well
beacon-chain/blockchain/head.go
Outdated
root := make([]byte, 32) | ||
copy(root, s.head.root[:]) | ||
|
||
return bytesutil.ToBytes32(root) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
roots are 32 byte arrays, so they are passed by value. You can just do
return s.head.root
@@ -29,8 +29,7 @@ var validatorBalancesGaugeVec = promauto.NewGaugeVec( | |||
// and penalties over time, percentage gain/loss, and gives the end user a better idea | |||
// of how the validator performs with respect to the rest. | |||
func (v *validator) LogValidatorGainsAndLosses(ctx context.Context, slot uint64) error { | |||
|
|||
if slot%params.BeaconConfig().SlotsPerEpoch != 0 || slot < params.BeaconConfig().SlotsPerEpoch { | |||
if slot%params.BeaconConfig().SlotsPerEpoch != 0 || slot <= params.BeaconConfig().SlotsPerEpoch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a bug, caught it via new test here
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} | ||
} | ||
cpt := s.headState.FinalizedCheckpoint() | ||
|
||
cpt := state.CopyCheckpoint(s.finalizedCheckpt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this beneath the equality check and just compare s.finalizedCheckpt.Root in bytes.Equal? Might save some copies
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion. Done
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} | ||
} | ||
|
||
cpt := s.headState.CurrentJustifiedCheckpoint() | ||
cpt := state.CopyCheckpoint(s.justifiedCheckpt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
return ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} | ||
} | ||
|
||
cpt := s.headState.PreviousJustifiedCheckpoint() | ||
cpt := state.CopyCheckpoint(s.prevJustifiedCheckpt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
} | ||
|
||
return s.headState.Copy(), nil | ||
headState, err := s.beaconDB.HeadState(ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update cache if we have a cache miss?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not here. That's what the PR aim to avoid. Update individual head field. If there's a miss setHead
will be used during init
…prysm into better-head-obj
* Done * Fixed lock * Fixed all the tests * Comments * Fixed more tests * Merge branch 'master' into better-head-obj * Fixed more tests * Merge branch 'better-head-obj' of git+ssh://github.com/prysmaticlabs/prysm into better-head-obj * Prestons feedback & fixed test * Nishant's feedback * Participation edge case * Gaz * Merge branch 'master' into better-head-obj * Merge branch 'master' of git+ssh://github.com/prysmaticlabs/prysm into better-head-obj * Raul's feedback * Merge branch 'better-head-obj' of git+ssh://github.com/prysmaticlabs/prysm into better-head-obj
* Done * Fixed lock * Fixed all the tests * Comments * Fixed more tests * Merge branch 'master' into better-head-obj * Fixed more tests * Merge branch 'better-head-obj' of git+ssh://github.com/prysmaticlabs/prysm into better-head-obj * Prestons feedback & fixed test * Nishant's feedback * Participation edge case * Gaz * Merge branch 'master' into better-head-obj * Merge branch 'master' of git+ssh://github.com/prysmaticlabs/prysm into better-head-obj * Raul's feedback * Merge branch 'better-head-obj' of git+ssh://github.com/prysmaticlabs/prysm into better-head-obj
Problem statement: There's too many variables that defines head for chain service.
Example in initial chain info:
A problem could be, if
headSlot
changes itself, then it changes head root while head state and head block remain its own version 😢To make it better, we define a head object:
To update the head object:
To retrieve from the head object, it's copy by default:
And now to initialize chain info:
This PR also cleaned up general head code by moving function to its proper location. Will list out those changes via inline comments