Implement traversal based early termination #3337
Open
+935
−44
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This commit makes the early termination logic of the snowflake poll consider also transitive voting. A block
b0
is transitively voted by all votes for blockb1
ifb0
is an ancestor ofb1
.This transitive termination logic also works for shard common block prefixes. If block
b0
is a direct ancestor ofb1
andb2
and the latter have a shared prefix, then the logic in this commit may not early terminate the vote if a future vote might improve the confidence of the shared prefix, as it correspons to a snowflake instance.Note: I will rename the file name
early_term_no_traversal.go
after this is merged. I didn't rename them in the same commit so that it will be easy to distinguish between old code and new code.Why this should be merged
Considering transitive votes in early termination logic improves consensus performance by reducing the time to block finalization due to earlier termination than when not taking into account transitive voting.
How this works
When the early termination logic is asked whether to terminate or not, it creates a graph out of the votes, where each ID of a block corresponds to a vertex. Parent vertices point to their descendants and descendants to their parents.
When considering how many votes for a block ID exist, the direct vote as well as the votes for the descendants are now taken int account.
Additionally, in order to adhere to the same logic that snowman employs for the bit decomposition of blocks, the termination logic also takes into account votes for shared bit prefixes of block IDs. For each vertex, its direct descendants are observed, and a graph of shared prefixes is built. Every inner vertex in the graph that corresponds to a unary node that represents a shared prefix is also taken account in transitive voting.
How this was tested
Unit tests for added code are included.
I ran a modified build on mainnet for 24 hours alongside a regular build and observed that transitive voting reduces occurrence of consensus rounds lasting more than 1200 milliseconds from 14% to 1.5% on mainnet.
The following graphs show the latency of consensus rounds as a function of time on mainnet.
Without transitive voting:
With transitive voting: