{"id":20388342,"url":"https://github.com/erwin-kok/kotlin-libp2p","last_synced_at":"2025-04-12T10:38:04.720Z","repository":{"id":177914860,"uuid":"657965305","full_name":"erwin-kok/kotlin-libp2p","owner":"erwin-kok","description":"libp2p implementation in Kotlin (see: https://libp2p.io/)","archived":false,"fork":false,"pushed_at":"2024-01-29T11:27:19.000Z","size":2209,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-26T05:33:12.482Z","etag":null,"topics":["ipfs","kotlin","kotlin-coroutines","libp2p","libp2p-muxer","libp2p-security","libp2p-transport","p2p","p2p-network"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/erwin-kok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-06-24T10:51:34.000Z","updated_at":"2025-02-07T01:59:25.000Z","dependencies_parsed_at":"2024-01-29T13:29:09.318Z","dependency_job_id":"3162a41d-4cca-4482-9f08-49d198525be2","html_url":"https://github.com/erwin-kok/kotlin-libp2p","commit_stats":null,"previous_names":["erwin-kok/kotlin-libp2p"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fkotlin-libp2p","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fkotlin-libp2p/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fkotlin-libp2p/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erwin-kok%2Fkotlin-libp2p/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erwin-kok","download_url":"https://codeload.github.com/erwin-kok/kotlin-libp2p/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248555513,"owners_count":21123918,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ipfs","kotlin","kotlin-coroutines","libp2p","libp2p-muxer","libp2p-security","libp2p-transport","p2p","p2p-network"],"created_at":"2024-11-15T03:08:53.873Z","updated_at":"2025-04-12T10:38:04.691Z","avatar_url":"https://github.com/erwin-kok.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003ca href=\"libp2p.io\"\u003e\u003cimg width=\"250\" src=\"https://github.com/libp2p/libp2p/blob/master/logo/black-bg-2.png?raw=true\" alt=\"libp2p hex logo\" /\u003e\u003c/a\u003e\n\u003c/h1\u003e\n\n# kotlin-libp2p\n\n[![ci](https://github.com/erwin-kok/kotlin-libp2p/actions/workflows/ci.yaml/badge.svg)](https://github.com/erwin-kok/kotlin-libp2p/actions/workflows/ci.yaml)\n[![Maven Central](https://img.shields.io/maven-central/v/org.erwinkok.libp2p/libp2p-core)](https://central.sonatype.com/artifact/org.erwinkok.libp2p/libp2p-core)\n[![Kotlin](https://img.shields.io/badge/kotlin-1.9.0-blue.svg?logo=kotlin)](http://kotlinlang.org)\n[![License](https://img.shields.io/github/license/erwin-kok/kotlin-libp2p.svg)](https://github.com/erwin-kok/kotlin-libp2p/blob/master/LICENSE)\n\n## Disclaimer\n\nWelcome to my personal pet project! This project is currently under heavy development (WIP), and as such I do not\nguarantee functionality, stable interfaces and/or operation without any bugs/issues (See also [`LICENSE`](LICENSE) for\nmore details). The current main goal of this project is educational, and to research new technologies.\n\n## libp2p overview\n\nTraditional communication is client-server based. The client initiates a connection to the server, and communicates with\nthe server using a protocol suited for that server. As an example: suppose we have two WhatsApp clients lets say `A`\nand `B`. And `A` wants to send a message to `B`. Typically, they both initiate a connection to the server. `A` sends a\nmessage to the server and tells the server to relay this message to `B`. The server knows both clients so this\ncommunication is pretty straightforward.\n\nIn a peer-to-peer network (P2P), this communication happens quite differently. There is no longer a server, only\nclients (commonly they are referred to as `nodes` or `peers`) organized in a mesh network, and they communicate directly\nto each other. For this to work a few challenges have to be solved:\n\n- How do the nodes know and find each other? In a client-server communication, the client established the connection to\n  the server, and the server is known by some pre-defined ip address (or addresses). In a P2P mesh network how to know\n  the ip address of the client? Potentially, the client is roaming which means its ip address can change over time.\n  **In libp2p this is solved by mDNS, DHT/Kademlia, and more**.\n\n- How can a node directly connect to another node? In client-server communication, the client initiates a connection to\n  the server. This is an outbound connection. However, in a P2P connection, a node connects directly to another node,\n  which is an inbound connection. Inbound connections are not always possible. Think of security (the router rejects\n  inbound connection attempts), but also think of NAT devices (what is the correct ip address? A node might know a\n  different ip address of itself than the outside world is able to connect to) **In libp2p this is solved by autonat,\n  holepunching, relay-service, and more**.\n\n- Which wire protocol to use? In a client-server network the used protocol is obvious: the server dictates the protocol\n  to be used, or else it rejects the connection. A server can easily support the current protocol version while also\n  supporting the older version(s) temporarily. A server can also force a client upgrade. In a P2P network this is not\n  obvious, because there are several nodes connected to each other. They all could have a different implementation with\n  different capabilities and with different versions **In libp2p this is solved by multiformats**.\n\n- How to distribute content? In a client/server setup, this is almost trivial. If node A wants to send something to node B it ’tags’ the message with an ‘address’ or ‘phone-number’ and sends it to the server. Since the server knows B it forwards this message directly to B. In a P2P connection, however, all nodes are interconnected via a mesh and perhaps A does not have a direct connection to B but has an indirect connection via some intermediate nodes C, D and E. If A wants to send something to B it has to send it to C. C has to send it to D and so on until it reaches B. It has to find a ‘route’ through all the nodes from A to B. And, for efficiency reasons, C should not forward the message to all its peers, because this will lead to congestion; all messages are send to each and every node. Ideally, C should send the message only to a node that is the most optimal node in the route to B (This is not always achievable). **In libp2p this is solved using different pubsub mechanisms**.\n\nThere already exists some P2P network protocols, but they lacked standardization. Libp2p standardizes the way nodes\ncommunicate to each other and has a solution for the above-mentioned issues (and more).\n\nSee for an in-depth description of libp2p, please see: https://libp2p.io/\n\n## Features\n\n- Multiformats. See my other repo: https://github.com/erwin-kok/multiformat\n    - [X] multiaddr\n    - [X] multibase\n    - [X] multicodec\n    - [X] multihash\n    - [X] multistream-select\n\n- Crypto\n    - [X] ED25519\n    - [X] ECDSA\n    - [X] SECp256k1\n    - [X] RSA\n\n- Transports\n    - [X] Tcp\n    - [ ] Quic (planned)\n\n- Muxers\n    - [X] Mplex\n    - [ ] Yamux (planned)\n    - [ ] Quic (planned)\n\n- Security\n    - [X] Noise\n    - [ ] Tls (planned)\n    - [ ] Quic (planned)\n\n- Protocols\n    - [X] Identify\n    - [X] Ping\n    - [ ] DHT/Kademlia (planned)\n    - [ ] GossipSub (planned)\n\n- Peer discovery\n    - [ ] mDNS (planned)\n    - [ ] DHT/Kademlia (planned)\n\n- Datastore\n    - [X] RocksDB\n\n## Getting started\n\nFirst add the proper dependencies to your project:\n\nKotlin DSL:\n\n```kotlin\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation(\"org.erwinkok.result:libp2p-xxx:$latest\")\n}\n```\n\n`libp2p-core` is mandatory, other dependencies are optional depending on your needs. For example, if you need tcp\ntransport, include `libp2p-transport-tcp`, or if you want the mplex muxer include `libp2p-muxer-plex`.\n\nIn your code, first create a host:\n\n```kotlin\nval hostBuilder = host {\n    identity(localIdentity)\n    muxers {\n        mplex()\n    }\n    securityTransport {\n        noise()\n    }\n    transports {\n        tcp()\n    }\n    swarm {\n        dialTimeout = 10.minutes\n        listenAddresses {\n            multiAddress(\"/ip4/0.0.0.0/tcp/10333\")\n        }\n    }\n    datastore(datastore)\n}\n\nval host = hostBuilder.build(scope)\n    .getOrElse {\n        logger.error { \"The following errors occurred while creating the host: ${errorMessage(it)}\" }\n        return@runBlocking\n    }\n```\n\nThe layout is hopefully clear: for example, the code above will use `tcp` as a transport, `noise` for security and\n`mplex` as a muxer.\n\nThen you can add a handler:\n\n```kotlin\nhost.setStreamHandler(ProtocolId.of(\"/chat/1.0.0\")) {\n    chatHandler(it)\n}\n```\n\nThis means that if a peer connects and requests the `/chat/1.0.0` protocol, the corresponding handler will be called.\n\nTo call a peer and open a new stream, use the following code:\n\n```kotlin\nval stream = host.newStream(aPeerId, ProtocolId.of(\"/chat/1.0.0\"))\n    .getOrElse {\n        logger.error { \"Could not open chat stream with peer: ${errorMessage(it)}\" }\n        return\n    }\nchatHandler(stream)\n```\n\nThis tries to connect to peer `aPeerId` and tries to open a new stream for protocol `/chat/1.0.0`. If it fails, it\nreturns if it succeeds it progresses to the chatHandler.\n\nSee also the example application in `examples/chat`.\n\nTo use this sample application, start the application. It will create a new random LocalIdentity (key-pair) and logs the\naddress on which it listens on the output:\n\n```shell\n[main] o.e.l.a.ApplicationKt$main$1: Local addresses the Host listens on: /ip4/0.0.0.0/tcp/10333/p2p/12D3KooWDfaEJxpmjbFLb9wUakCd6Lo6LRntaV3drb4EaYZRtYuY \n```\n\nIn the libp2p-Go repository you can find `chat` in the `examples` directory. Then you can connect to the running instance\nby using:\n\n```shell\n./chat -d /ip4/0.0.0.0/tcp/10333/p2p/12D3KooWDfaEJxpmjbFLb9wUakCd6Lo6LRntaV3drb4EaYZRtYuY\n```\n\nOn both sides it should mention that a connection is established.\n\n## Contact\n\nIf you want to contact me, please write an e-mail to: \"erwin (DOT) kok (AT) protonmail (DOT) com\"\n\n## Acknowledgements\n\nThis work is largely based on the awesome [go-libp2p](https://github.com/libp2p/go-libp2p) implementation. This work would not have been possible without their\neffort. Please consider giving kudos to the go-libp2p authors.\n(See also [`ACKNOWLEDGEMENTS`](ACKNOWLEDGEMENTS.md))\n\n## License\n\nThis project is licensed under the BSD-3-Clause license, see [`LICENSE`](LICENSE) file for more details. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferwin-kok%2Fkotlin-libp2p","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferwin-kok%2Fkotlin-libp2p","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferwin-kok%2Fkotlin-libp2p/lists"}