Skip to content

Implement search for membership vector #71

Description

@thep2p

Context

search_by_mem_vec is the algorithm that, given a target MembershipVector, finds the node in the skip graph whose membership vector has the longest common prefix with the target. It is a prerequisite for BaseNode::join (#66), which uses it at each level to find prefix-matching neighbors.

The stub exists at src/node/core.rs:165 as todo!().

Algorithm

The search works level by level, starting from the highest level down to 0. At each level, the current node checks whether either neighbor has a longer common-prefix match with the target than itself. If so, it forwards the search to that neighbor. If neither neighbor improves the match, it drops to the level below. If it reaches level 0 with no improvement, it returns itself as the best match.

Pseudocode in codebase terms:

// Executed at node v upon receiving (origin_id, target_mv, level):

let my_match = common_prefix_length(v.mem_vec, target_mv)

if my_match == MV_BITS:
    // exact match: this node is the target
    return MemVecSearchRes { result: v.id, match_len: my_match }

while level >= 0:
    right = v.lt.get_entry(level, Direction::Right)
    left  = v.lt.get_entry(level, Direction::Left)

    if right.is_some() && common_prefix_length(right.mem_vec, target_mv) > my_match:
        forward (origin_id, target_mv, level) to right
        return

    if left.is_some() && common_prefix_length(left.mem_vec, target_mv) > my_match:
        forward (origin_id, target_mv, level) to left
        return

    level -= 1

// No better neighbor found at any level: self is the best match
return MemVecSearchRes { result: v.id, match_len: my_match }

Current signature problem

The existing stub reuses IdSearchReq / IdSearchRes:

fn search_by_mem_vec(&self, _req: &IdSearchReq) -> anyhow::Result<IdSearchRes>;

This is wrong. IdSearchReq carries target: Identifier (a numerical ID) and a single Direction. The membership vector search needs:

  • target: MembershipVector (not an Identifier)
  • no fixed direction — both neighbors are checked at each level
  • start_level: LookupTableLevel

New request/response types are required (e.g. MemVecSearchReq / MemVecSearchRes), along with new Event variants (SearchByMemVecRequest / SearchByMemVecResponse).

Work breakdown

  1. common_prefix_length — add a method to MembershipVector that returns the number of leading bits two membership vectors share.
  2. MemVecSearchReq / MemVecSearchRes — new model types in src/core/model/search.rs carrying target: MembershipVector and start_level: LookupTableLevel.
  3. Event variants — add SearchByMemVecRequest(MemVecSearchReq) and SearchByMemVecResponse(MemVecSearchRes) to src/network/mod.rs.
  4. Core::search_by_mem_vec — fix the signature in src/node/core.rs and implement the algorithm in BaseCore.
  5. BaseNode routing — handle the two new event variants in process_incoming_event.
  6. Tests — unit tests for common_prefix_length; integration tests for single-hop and multi-hop membership vector search over MockNetwork.

Relationship to other issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions