Skip to content
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

Track uptime & distribute rewards based on it #618

Merged
merged 29 commits into from
Nov 21, 2019
Merged

Track uptime & distribute rewards based on it #618

merged 29 commits into from
Nov 21, 2019

Conversation

gakonst
Copy link
Contributor

@gakonst gakonst commented Nov 20, 2019

Description

Will close #457. Idea is that we track a validator's uptime by the bitmap from my previous PR.

  • We can safely assume the bitmap represents 2/3rds of the validators, so we can multiply the number of 1s in the bitmap by 1.5 (3/2) to get an upper bound on the number of validators in that epoch.
  • We store each epoch's uptimes, but we could probably just store the latest epoch only
  • The "forgiving" factor means that a validator will get always a +1 point if they signed a block, and they will still get a +1, even if they did not sign it, as long as they had at least 1 signature in a sliding window before the current block.
  • We do not score for the first window blocks per epoch

Tested

Other changes

  • extra cli parameter for the window which defaults to 12

cmd/utils/flags.go Show resolved Hide resolved
consensus/istanbul/backend/pos.go Outdated Show resolved Hide resolved
}

// the uptimes array is aligned with the validator set
validatorUptime := uptimes[validatorIndex].Score / (sb.EpochSize() - sb.LookbackWindow() + 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this return 0? I think we actually want (uptimes[validatorIndex].Score * 10^24) / (sb.EpochSize() - sb.LookbackWindow() + 1)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah logic in the pos file was still WIP, should be fixed now

var validatorsSize uint64
if len(uptime) == 0 {
// the number of validators is upper bound by 3/2 of the number of 1s in the bitmap
// TODO: due to this maybe we create an uptimeScore array which is 1 element bigger than required
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So actually, since we're recording the uptime based on the signatures on the previous block, of which there may be more than 2F+1, we're likely to create an uptimeScore array much bigger than required


signedValidatorsBitmap := extra.ParentAggregatedSeal.Bitmap
uptime := bc.GetAccumulatedUptime()
uptime = updateUptime(uptime, block.NumberU64(), signedValidatorsBitmap, bc.chainConfig.Istanbul.LookbackWindow)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the per-epoch reset happening?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the uptimes per epoch to be saved in different keys, so there is no direct need to save the data in order to calculate the uptime properly

core/blockchain.go Outdated Show resolved Hide resolved
core/rawdb/accessors_chain.go Outdated Show resolved Hide resolved
@gakonst gakonst force-pushed the gakonst/uptime branch 2 times, most recently from 78a5d66 to a5f7ce0 Compare November 20, 2019 23:08
@asaj asaj assigned asaj and kevjue and unassigned asaj and gakonst Nov 21, 2019
if bitmap.Bit(i) == 1 {
// update their latest signed block and reward them
uptime[i].LastSignedBlock = blockNumber
if blockNumber >= firstBlockInEpoch+window-1 {
Copy link
Contributor

@kevjue kevjue Nov 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this should be firstBlockInEpoch + window + 1. The aggregatedParentSignatures for the firstBlockInEpoch will be for a different valset than the current valset.

@asaj asaj marked this pull request as ready for review November 21, 2019 06:11
@asaj asaj changed the title [WIP] Track uptime & distribute rewards based on it Track uptime & distribute rewards based on it Nov 21, 2019
uptime[i].LastSignedBlock = blockNumber - 1
}

// If we are within the validator uptime tally window, then update the validator's score if it's last signed block is within
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// If we are within the validator uptime tally window, then update the validator's score if it's last signed block is within
// If we are within the validator uptime tally window, then update the validator's score if its last signed block is within


// If we are within the validator uptime tally window, then update the validator's score if it's last signed block is within
// the lookback window
if valScoreTallyFirstBlockNum <= blockNumber && blockNumber <= valScoreTallyLastBlockNum {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, nit: we could maybe extract this and the valScoreTally{First, Last}BlockNum functions together to another function, isInLookbackWindow

if valScoreTallyFirstBlockNum <= blockNumber && blockNumber <= valScoreTallyLastBlockNum {
lastSignedBlock := uptime[i].LastSignedBlock
// TODO (kevjue) add comment about 2nd check
if signedBlockWindowFirstBlockNum <= lastSignedBlock && lastSignedBlock <= signedBlockWindowLastBlockNum {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if signedBlockWindowFirstBlockNum <= lastSignedBlock && lastSignedBlock <= signedBlockWindowLastBlockNum {
// increase our score as long as we signed at least one block within the lookback window,
// (even if we did not sign on the current block)
if signedBlockWindowFirstBlockNum <= lastSignedBlock && lastSignedBlock <= signedBlockWindowLastBlockNum {

if bc.engine.Protocol().Name == "istanbul" {
// The epoch's first block's aggregated parent signatures is for the previous epoch's valset.
// We can ignore updating the tally for that block.
if !istanbul.IsFirstBlockOfEpoch(block.NumberU64(), bc.chainConfig.Istanbul.Epoch) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! There's probably merit in us documenting all the edge cases we've encountered so far in this and my previous PR about parent seals regarding epoch transitions

core/blockchain_test.go Outdated Show resolved Hide resolved
core/rawdb/accessors_chain.go Outdated Show resolved Hide resolved
core/rawdb/accessors_chain.go Outdated Show resolved Hide resolved
Copy link
Contributor

@asaj asaj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Mostly nits

cmd/utils/flags.go Outdated Show resolved Hide resolved
consensus/istanbul/backend/engine.go Outdated Show resolved Hide resolved
consensus/istanbul/backend/pos.go Outdated Show resolved Hide resolved
consensus/istanbul/backend/pos.go Outdated Show resolved Hide resolved
consensus/istanbul/backend/pos.go Show resolved Hide resolved
core/rawdb/accessors_chain.go Outdated Show resolved Hide resolved
core/rawdb/accessors_chain.go Outdated Show resolved Hide resolved
core/rawdb/accessors_chain.go Outdated Show resolved Hide resolved
core/rawdb/accessors_chain_test.go Outdated Show resolved Hide resolved
eth/backend.go Outdated Show resolved Hide resolved
@asaj asaj merged commit 3ecd94a into master Nov 21, 2019
@gakonst gakonst deleted the gakonst/uptime branch November 21, 2019 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Full nodes SBAT track validator uptime within an epoch
4 participants