Algorithm-Kademlia
view release on metacpan or search on metacpan
# State management for iterative lookups
my $search = Algorithm::Kademlia::Search->new(
target_id_bin => $target_key,
alpha => 3
);
$search->add_candidates($rt->find_closest($target_key));
while (!$search->is_finished) {
my @to_query = $search->next_to_query();
for my $node (@to_query) {
# ... Send FIND_NODE RPC to $node ...
# If response: $search->mark_responded($node->{id}, @found_peers);
# If failure: $search->mark_failed($node->{id});
}
}
my @results = $search->best_results();
```
# DESCRIPTION
`Algorithm::Kademlia` provides the mathematical and structural foundations for a Kademlia Distributed Hash Table
(DHT). It is designed to be protocol-agnostic, meaning it only handles the XOR-metric distance calculations, the
k-bucket routing table logic, and the search state management.
This module is suitable for building BitTorrent-compatible DHTs, libp2p Kademlia implementations, or custom
peer-to-peer storage systems.
# FUNCTIONS
These are bitwise logic utilities for the Kademlia XOR metrics.
## `xor_distance( $id1, $id2 )`
Returns the bitwise XOR of two binary strings.
```perl
my $id1 = pack('H*', '00' x 20);
my $id2 = pack('H*', 'ff' x 20);
my $dist = xor_distance($id1, $id2);
say unpack('H*', $dist); # ffffffffffffffffffffffffffffffffffffffff
```
## `xor_bucket_index( $id1, $id2 )`
Calculates the index of the k-bucket that `$id2` would fall into relative to `$id1`. Returns `undef` if the IDs are
identical.
The index corresponds to the bit position of the most significant bit that differs between the two IDs. For 160-bit
IDs, the result is between 0 and 159.
```perl
my $local = pack('H*', '00' x 20);
my $peer = pack('H*', '80' . ('00' x 19)); # 160th bit differs
my $idx = xor_bucket_index($local, $peer);
say $idx; # 159
```
# Algorithm::Kademlia::RoutingTable
This class implements the 160 k-bucket structure (or appropriate size for the ID length provided). Peers are bucketed
by their XOR distance from the local node ID.
## `new( local_id_bin => ..., [ k => 20 ] )`
Constructor. `local_id_bin` is the binary string of the local node's ID.
```perl
my $rt = Algorithm::Kademlia::RoutingTable->new(
local_id_bin => $my_id_bin,
k => 20
);
```
## `add_peer( $id_bin, $data )`
Adds a peer to the appropriate bucket.
- If the peer is already present, it is moved to the "most recently seen" position (the tail of the bucket).
- If the bucket is full (reaches size `k`), it returns the "least recently seen" peer (the head of the bucket). According to the Kademlia whitepaper, the caller should ping this stale peer.
- If the bucket is not full, the peer is added and it returns `undef`.
```perl
my $stale = $rt->add_peer($id, { ip => '1.2.3.4', port => 4444 });
if ($stale) {
# Bucket full! Ping $stale->{data}{ip}
}
```
## `evict_peer( $id_bin )`
Removes a peer from the routing table. Usually called after a stale peer fails a ping check.
```
$rt->evict_peer($stale_id);
```
## `find_closest( $target_id_bin, [ $count ] )`
Returns a list of up to `$count` (defaults to `k`) peers closest to the target ID according to the XOR metric.
```perl
my @peers = $rt->find_closest($target_key, 10);
for my $peer (@peers) {
say 'Node ' . unpack('H*', $peer->{id}) . ' is at ' . $peer->{data}{ip};
}
```
## `size( )`
Returns the total number of peers across all buckets.
```
say 'Routing table has ' . $rt->size . ' peers';
```
# Algorithm::Kademlia::Storage
A simple in-memory key-value store intended to hold the DHT data.
## `new( [ ttl => 86400 ] )`
( run in 0.512 second using v1.01-cache-2.11-cpan-140bd7fdf52 )