Algorithm-Kademlia

 view release on metacpan or  search on metacpan

lib/Algorithm/Kademlia.pod  view on Meta::CPAN

=head1 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.

=head2 C<new( local_id_bin =E<gt> ..., [ k =E<gt> 20 ] )>

Constructor. C<local_id_bin> is the binary string of the local node's ID.

    my $rt = Algorithm::Kademlia::RoutingTable->new(
        local_id_bin => $my_id_bin,
        k            => 20
    );

=head2 C<add_peer( $id_bin, $data )>

Adds a peer to the appropriate bucket.

=over

=item * If the peer is already present, it is moved to the "most recently seen" position (the tail of the bucket).

=item * If the bucket is full (reaches size C<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.

=item * If the bucket is not full, the peer is added and it returns C<undef>.

=back

    my $stale = $rt->add_peer($id, { ip => '1.2.3.4', port => 4444 });
    if ($stale) {
        # Bucket full! Ping $stale->{data}{ip}
    }

=head2 C<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);

=head2 C<find_closest( $target_id_bin, [ $count ] )>

Returns a list of up to C<$count> (defaults to C<k>) peers closest to the target ID according to the XOR metric.

    my @peers = $rt->find_closest($target_key, 10);
    for my $peer (@peers) {
        say 'Node ' . unpack('H*', $peer->{id}) . ' is at ' . $peer->{data}{ip};
    }

=head2 C<size( )>

Returns the total number of peers across all buckets.

    say 'Routing table has ' . $rt->size . ' peers';

=head1 Algorithm::Kademlia::Storage

A simple in-memory key-value store intended to hold the DHT data.

=head2 C<new( [ ttl =E<gt> 86400 ] )>

Constructor. C<ttl> is the time-to-live for entries in seconds.

    my $storage = Algorithm::Kademlia::Storage->new( ttl => 3600 );

=head2 C<put( $key_bin, $value_bin, [ $publisher_id_bin ] )>

Stores a value.

    $storage->put($cid_bin, $data_bin, $provider_id);

=head2 C<get( $key_bin )>

Retrieves a value. Returns C<undef> if the key is missing or has expired.

    my $data = $storage->get($cid_bin);
    die 'Expired or not found' unless defined $data;

=head2 C<entries( )>

Returns a hash reference of all non-expired entries in the store.

    my %all = $storage->entries();
    for my ($key, $info) (%all) {
        say 'Key: ' . unpack('H*', $key) . ' Value: ' . $info->{value};
    }

=head1 Algorithm::Kademlia::Search

A state manager for the iterative Kademlia lookup algorithm. It tracks which nodes have been queried, which have
responded, and which have failed.

=head2 C<new( target_id_bin =E<gt> ..., [ k =E<gt> 20, alpha =E<gt> 3 ] )>

Constructor. C<alpha> is the concurrency parameter (how many parallel queries to allow).

    my $search = Algorithm::Kademlia::Search->new(
        target_id_bin => $target_key,
        alpha         => 3
    );

=head2 C<add_candidates( @peers )>

Adds new potential nodes to the search shortlist.

    $search->add_candidates( $rt->find_closest($target_key) );

=head2 C<pending_queries( )>

Returns a list of nodes that have been queried but have not yet responded or failed.

    my @waiting = $search->pending_queries();
    say 'Waiting for ' . scalar(@waiting) . ' nodes...';

=head2 C<next_to_query( )>

Returns a list of up to C<alpha> nodes that have not yet been queried, sorted by proximity to the target.

    my @to_query = $search->next_to_query();
    # Now send your RPCs to these nodes...

=head2 C<mark_responded( $id_bin, @new_peers )>



( run in 0.569 second using v1.01-cache-2.11-cpan-39bf76dae61 )