Skip to content

VLC double-increment on event receive inflates vector clock #22

Description

@ABresting

Bug

ConsensusEngine::add_event() and receive_event_from_network() both call vlc.merge() followed by vlc.tick() when processing a received event. However, VLC::merge() internally calls VLCSnapshot::receive(), which already performs the increment (merge vector clocks → set logical_time = max + 1 → increment local node's vector clock entry).

The subsequent vlc.tick() calls VLCSnapshot::increment() again, resulting in two increments per receive — the local node's vector clock entry advances by 2 and logical_time advances by 2 for every single received event.

Impact

  • Vector clock entries grow at 2x the correct rate on receive paths
  • logical_time inflates faster than it should, causing should_fold() (VLC delta threshold) to trigger prematurely
  • Causal ordering comparisons (happens_before) are still correct (monotonicity is preserved), but the clock values are unnecessarily inflated

Root cause

// consensus/src/engine.rs — add_event() and receive_event_from_network()
{
    let mut vlc = self.vlc.write().await;
    vlc.merge(&event.vlc_snapshot);  // calls receive() which already increments
    vlc.tick();                       // redundant second increment
}

VLC::merge()VLCSnapshot::receive():

pub fn receive(&mut self, other: &VLCSnapshot, local_node_id: &str) {
    self.vector_clock.merge(&other.vector_clock);
    self.logical_time = self.logical_time.max(other.logical_time) + 1;  // +1
    self.vector_clock.increment(local_node_id);                          // increment
    self.physical_time = Self::current_physical_time();
}

Fix

Remove the redundant vlc.tick() after vlc.merge() in both add_event() and receive_event_from_network(). The create_event() and tick_and_get_vlc() paths are correct (they only call tick() once for local event creation).

Reference

VLC update rules per Chrono: Building a Verifiable Logical Clock for P2P NetworksUPDATE(id, c, [c_received]) performs merge + single increment. The receive path should not double-increment.

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions