Skip to content

network: dynamic vote compression #6351

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

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft

Conversation

cce
Copy link
Contributor

@cce cce commented May 30, 2025

Summary

This adds to #6276 a StatefulEncoder and StatefulDecoder, that compress votes using HPACK-style references to values from previous votes. It provides better than 50% compression given different table sizes.

Test Plan

  • Unit tests in vpack package
  • Ensure full test coverage in vpack package

Copy link

codecov bot commented May 30, 2025

Codecov Report

Attention: Patch coverage is 98.43444% with 8 lines in your changes missing coverage. Please review.

Project coverage is 50.65%. Comparing base (18990e0) to head (571d707).
Report is 61 commits behind head on master.

Files with missing lines Patch % Lines
network/vpack/dynamic_vpack.go 97.97% 6 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6351      +/-   ##
==========================================
- Coverage   51.82%   50.65%   -1.17%     
==========================================
  Files         652      656       +4     
  Lines       87425   110899   +23474     
==========================================
+ Hits        45307    56177   +10870     
- Misses      39249    51858   +12609     
+ Partials     2869     2864       -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

// not found: send literal and add to window
hdr1 |= 0 << hdr1PropShift // set 000
e.proposalWindow.insertNew(prop)
// write proposal bytes as StatelessEncoder would
Copy link
Contributor

Choose a reason for hiding this comment

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

consider delegating to stateless encoder/decoder there to have stateful less dependent on stateless impl details?

Copy link
Contributor Author

@cce cce Jun 26, 2025

Choose a reason for hiding this comment

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

I'm not sure how to delegate it though without some interface/function abstraction that will slow it down, because StatelessEncoder's job is to read msgpack and output the compressed format that is an input here, and StatelessDecoder's job is to output msgpack format, so there is no subroutine I can think of that reads a compressed format and does hdr0 & bitDig check (set by StatelessEncoder) and then re-outputs the same compressed format..

// to 7 entries, encoded using 3 bits in the header byte. This is enough to
// provide effective compression, since usually almost all the votes in a round
// are for the same proposal value.
type propWindow struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

this is clever one!

@cce cce requested a review from Copilot July 12, 2025 05:13
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds dynamic vote compression by introducing StatefulEncoder and StatefulDecoder, leveraging HPACK-style references to prior vote fields to reduce message size.

  • Replaced manual varuint byte-length logic in StatelessDecoder with a shared msgpVaruintRemaining helper.
  • Implemented a small sliding window (propWindow) for proposal entries and a 2-way set-associative LRU table (lruTable) for other vote fields.
  • Added comprehensive unit tests for proposal window, LRU table, and the new stateful compression layer.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
network/vpack/vpack.go Updated headerSize comment; refactored varuint decoding in StatelessDecoder
network/vpack/msgp.go Added msgpVaruintRemaining; updated readUintBytes to use it
network/vpack/proposal_window.go New propWindow implementation for HPACK-style proposal compression
network/vpack/proposal_window_test.go Unit tests for proposal window behavior
network/vpack/lru_table.go New 2-way set-associative lruTable for dynamic references
network/vpack/lru_table_test.go Unit tests for LRU table insert, lookup, and eviction
network/vpack/dynamic_vpack.go New StatefulEncoder/StatefulDecoder and shared dynamicTableState
network/vpack/dynamic_vpack_test.go Tests covering stateful compression/decompression and error paths
Comments suppressed due to low confidence (2)

network/vpack/vpack.go:42

  • [nitpick] The comment for headerSize is unclear—consider clarifying that it defines two header bytes (mask and flags) rather than referencing specific encoder types.
	headerSize = 2 // 1 byte for StatelessEncoder, 1 byte for StatefulEncoder

network/vpack/proposal_window.go:48

  • The loop uses 'for i := range w.size', but w.size is an int, not a slice or array. This will not compile. Change it to a classic for-loop: 'for i := 0; i < w.size; i++ {'.
	for i := range w.size {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants