froozen / kademlia Goto Github PK
View Code? Open in Web Editor NEWA haskell library implementing the Kademlia DHT
License: BSD 3-Clause "New" or "Revised" License
A haskell library implementing the Kademlia DHT
License: BSD 3-Clause "New" or "Revised" License
I tried connecting three nodes. Killing one of the nodes and waiting for a few minutes, the original bootstrap node disappears as well. Trying to reconnect to the bootstrap node causes a 'NodeDown'.
By running dead-code-detection on my project, I discovered that the delete
function in Network.Kademlia.Tree
is dead code. My intuition tells me that this shouldn't be the case and I messed up the implementation of timing out peers.
Hi, we packaged kademlia
on NixOS, but unfortunately our central builds fail with a timeout error during the test suite run. Is it normal for that test suite to run for 2+ hours? Please see http://hydra.nixos.org/build/25334361/log/raw for a complete build log.
This library has practically every type parameterised on two type variables, 'i' and 'a'.
Simplified view: i
represents a key, a
represents a value.
The only thing we ever assume about i
and a
are that they have Serialize
instances, but there's no reason to do it that way rather than to just have two concrete newtypes over ByteString
, called Key
and Value
, and then write a wrapper module that uses Serialize
.
I think it's not only unnecessary, but this design is worse. The current approach encourages orphan instances, makes code harder to read, and removes opportunities for optimisation.
I can connect two peers just fine, but from the third node onwards I get 'IDClash' on connecting to the network. I'm printing debugPeers
and I can see that the third node contains itself in the peer list. The first two only contains the other peer nodes.
I'm using the following for testing:
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [kademlia cryptonite uuid])"
{-# Language DeriveGeneric #-}
{-# Language OverloadedStrings #-}
{-# Language LambdaCase #-}
module Main where
import qualified Network.Kademlia as K
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C
import qualified Data.ByteString.Lazy as BL
import qualified Data.Binary as BS
import Control.Arrow (first)
import GHC.Generics (Generic)
import Control.Exception
import System.Environment (getArgs)
import Control.Monad (when, forever)
import Control.Concurrent (threadDelay, myThreadId)
import Data.Monoid ((<>))
import Crypto.Hash
import Data.ByteArray (convert)
data Person = Person { age :: Int , name :: String }
deriving (Show, Eq, Ord, Generic)
instance BS.Binary Person
instance K.Serialize Person where
toBS = BL.toStrict . BS.encode
fromBS bs =
let person = BS.decode (BL.fromStrict bs)
in Right (person, "")
keySize :: Int
keySize = 32
newtype KademliaID = KademliaID B.ByteString deriving (Show, Eq, Ord)
toKey :: B.ByteString -> KademliaID
toKey bs = KademliaID (convert (hashWith SHA256 bs))
instance K.Serialize KademliaID where
toBS (KademliaID bs)
| B.length bs >= keySize = B.take keySize bs
| otherwise = error "KademliaID to short!"
fromBS bs
| B.length bs >= keySize = Right . first KademliaID . B.splitAt keySize $ bs
| otherwise = Left "ByteString too short!"
withKademlia :: Int -> KademliaID -> (K.KademliaInstance KademliaID Person -> IO ()) -> IO ()
withKademlia port name f =
bracket (K.create port name)
K.close
f
debugger :: K.KademliaInstance KademliaID Person -> IO ()
debugger inst = forever $ do
peers <- fmap K.peer <$> K.dumpPeers inst
putStrLn $ show (length peers) <> " peers"
print peers
-- let key = (toKey "foobar")
-- K.lookup inst key >>= print
threadDelay 5000000
joinInstance :: Int -> KademliaID -> K.KademliaInstance KademliaID Person -> IO ()
joinInstance port name inst =
K.joinNetwork inst (K.Node (K.Peer "127.0.0.1" (fromIntegral port)) name) >>= \case
K.JoinSucces -> do
peers <- K.dumpPeers inst
print peers
when (length peers > 4) $ do
let key = (toKey "foobar")
let person = Person 25 "Alan Turing"
K.store inst key person
threadDelay 1000000
err -> print err
main :: IO ()
main =
getArgs >>= \case
[port, name] -> withKademlia (read port) (toKey $ C.pack name) debugger
[port, name, remotePort, remoteName] -> withKademlia (read port) (toKey $ C.pack name) (\inst -> joinInstance (read remotePort) (toKey $ C.pack remoteName) inst >> debugger inst)
./kademlia.hs 12345 hello
for starting a bootstrap node./kademlia.hs <port> $(uuidgen) 12345 hello
for starting a peerA declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.