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

Reduce usage of getBlock in consensus #3151

Merged
merged 33 commits into from
Jul 13, 2024
Merged

Conversation

StephenButtolph
Copy link
Contributor

@StephenButtolph StephenButtolph commented Jun 26, 2024

Why this should be merged

getBlock can result in DB reads due to it's usage of the VM.GetBlock function. If the same behavior can be performed with in-memory checks rather than with using VM.GetBlock, we should.

This also improves TestGetProcessingAncestor.

How this works

From the VM.GetBlock specification:

// Attempt to load a block.
//
// If the block does not exist, database.ErrNotFound should be returned.
//
// It is expected that blocks that have been successfully verified should be
// returned correctly. It is also expected that blocks that have been
// accepted by the consensus engine should be able to be fetched. It is not
// required for blocks that have been rejected by the consensus engine to be
// able to be fetched.

So, we can only rely on VM.GetBlock to return Accepted and Verified but not yet Decided blocks.

Additionally, pending contains the set of blocks that are awaiting issuance due to a transitive network request. Meaning that there is a block that is not locally known between a pending block and a Processing or Decided block.

  1. In Start, getBlock can be removed to explicitly use VM.GetBlock, as pending and nonVerifiedCache are both empty.
  2. In getProcessingAncestor there are 3 cases that we need to consider:
    a. VM.GetBlock would have returned a Verified but not yet Decided block. This case can never occur because, we already know that the provided block is not processing.
    b. VM.GetBlock would have previously returned an Accepted block. If this was the case, then we would have immediately dropped it in the next check. So dropping the vote early results in the same behavior.
    c. pending contained the block that we are looking for. In this case, we may have been able to continue looking for a Processing ancestor. However, we know that we would have never found such an ancestor, because if we were able to locally iterate and find a processing ancestor, then this block shouldn't be pending, it should have been attempted to be issued. Additionally, we know that initialVote has already been either Fulfilled or Abandoned, so we aren't running into a situation where the pending block is currently in the process of being issued.

How this was tested

  • CI

@StephenButtolph StephenButtolph added the consensus This involves consensus label Jun 26, 2024
@StephenButtolph StephenButtolph added the cleanup Code quality improvement label Jun 26, 2024
@StephenButtolph StephenButtolph self-assigned this Jun 26, 2024
Base automatically changed from remove-status-usage to master June 28, 2024 16:21
@StephenButtolph StephenButtolph added this to the v1.11.10 milestone Jul 11, 2024
Copy link
Contributor

@tsachiherman tsachiherman left a comment

Choose a reason for hiding this comment

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

The change looks great. Two comments:

  • The getProcessingAncestor, in the way being written, looks like it could get into a (theoretical) endless loop in case of a circle in the parents linked list. ( clearly, this would imply a serious issue elsewhere ).
  • I find the field name nonVerifiedCache to be somewhat confusing. The description is :
// A block is put into this cache if it was not able to be issued. A block
// fails to be issued if verification on the block or one of its ancestors
// occurs.
  • which implies it it should be called verifiedBlocksCache. alternatively, maybe "unissuedBlock" ? it might be a terminology issue, where we're using the terms (un)issued and verified synonymously ?

@StephenButtolph
Copy link
Contributor Author

  • The getProcessingAncestor, in the way being written, looks like it could get into a (theoretical) endless loop in case of a circle in the parents linked list. ( clearly, this would imply a serious issue elsewhere ).

This is true.

  • I find the field name nonVerifiedCache to be somewhat confusing. The description is :
// A block is put into this cache if it was not able to be issued. A block
// fails to be issued if verification on the block or one of its ancestors
// occurs.

The comment was incorrect. It should have referenced verification failing on either the block or one of its ancestors. I updated the comment. I also renamed a couple of the fields to be a bit more clear.

@StephenButtolph StephenButtolph added this pull request to the merge queue Jul 13, 2024
Merged via the queue into master with commit 693439a Jul 13, 2024
20 checks passed
@StephenButtolph StephenButtolph deleted the reduce-usage-of-get-block branch July 13, 2024 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cleanup Code quality improvement consensus This involves consensus
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants