*Add IPNS support

*Re-add in DHT
*Create ready helper function
This commit is contained in:
Derrick Hammer 2023-03-30 18:05:14 -04:00
parent 2ec2663ced
commit 74498c5691
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
2 changed files with 125 additions and 34 deletions

View File

@ -9,22 +9,25 @@
"build": "npm run compile && node ./dist-build/build.mjs dev" "build": "npm run compile && node ./dist-build/build.mjs dev"
}, },
"dependencies": { "dependencies": {
"@chainsafe/libp2p-noise": "^11.0.1", "@chainsafe/libp2p-gossipsub": "^6.2.0",
"@chainsafe/libp2p-noise": "^11.0.2",
"@chainsafe/libp2p-yamux": "^3.0.7", "@chainsafe/libp2p-yamux": "^3.0.7",
"@dao-xyz/libp2p-noise": "^11.1.3", "@dao-xyz/libp2p-noise": "^11.1.3",
"@helia/unixfs": "^1.1.0", "@helia/ipns": "^1.1.0",
"@helia/unixfs": "^1.2.1",
"@libp2p/bootstrap": "^6.0.3",
"@libp2p/crypto": "^1.0.14", "@libp2p/crypto": "^1.0.14",
"@libp2p/delegated-content-routing": "^4.0.1", "@libp2p/delegated-content-routing": "^4.0.3",
"@libp2p/delegated-peer-routing": "^4.0.1", "@libp2p/delegated-peer-routing": "^4.0.4",
"@libp2p/interface-metrics": "^4.0.5", "@libp2p/interface-metrics": "^4.0.5",
"@libp2p/interfaces": "^3.3.1", "@libp2p/interfaces": "^3.3.1",
"@libp2p/logger": "^2.0.6", "@libp2p/logger": "^2.0.7",
"@libp2p/mplex": "^7.1.1", "@libp2p/mplex": "^7.1.2",
"@libp2p/tcp": "^6.1.2", "@libp2p/tcp": "^6.1.4",
"@libp2p/utils": "^3.0.4", "@libp2p/utils": "^3.0.6",
"@lumeweb/kernel-swarm-client": "git+https://git.lumeweb.com/LumeWeb/kernel-swarm-client.git", "@lumeweb/kernel-swarm-client": "git+https://git.lumeweb.com/LumeWeb/kernel-swarm-client.git",
"@multiformats/mafmt": "^11.1.0", "@multiformats/mafmt": "^11.1.2",
"b4a": "^1.6.2", "b4a": "^1.6.3",
"blockstore-core": "^3.0.0", "blockstore-core": "^3.0.0",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"compact-encoding": "^2.11.0", "compact-encoding": "^2.11.0",
@ -38,6 +41,7 @@
"p-queue": "^7.3.4", "p-queue": "^7.3.4",
"private-ip": "^3.0.0", "private-ip": "^3.0.0",
"rewire": "^6.0.0", "rewire": "^6.0.0",
"runes2": "^1.0.10",
"serialize-error": "^11.0.0", "serialize-error": "^11.0.0",
"sodium-universal": "^4.0.0", "sodium-universal": "^4.0.0",
"streamx": "^2.13.2", "streamx": "^2.13.2",
@ -45,22 +49,22 @@
}, },
"devDependencies": { "devDependencies": {
"@helia/interface": "^0.0.0", "@helia/interface": "^0.0.0",
"@libp2p/interface-connection": "^3.1.0", "@libp2p/interface-connection": "^3.1.1",
"@libp2p/interface-peer-info": "^1.0.8", "@libp2p/interface-peer-info": "^1.0.9",
"@libp2p/interface-transport": "^2.1.1", "@libp2p/interface-transport": "^2.1.2",
"@libp2p/kad-dht": "^7.0.3", "@libp2p/kad-dht": "^7.0.3",
"@libp2p/peer-id": "^2.0.2", "@libp2p/peer-id": "^2.0.3",
"@libp2p/peer-id-factory": "^2.0.2", "@libp2p/peer-id-factory": "^2.0.3",
"@libp2p/websockets": "^5.0.5", "@libp2p/websockets": "^5.0.7",
"@lumeweb/kernel-dht-client": "git+https://git.lumeweb.com/LumeWeb/kernel-swarm-client.git", "@lumeweb/kernel-dht-client": "git+https://git.lumeweb.com/LumeWeb/kernel-swarm-client.git",
"@lumeweb/kernel-rpc-client": "git+https://git.lumeweb.com/LumeWeb/kernel-rpc-client.git", "@lumeweb/kernel-rpc-client": "git+https://git.lumeweb.com/LumeWeb/kernel-rpc-client.git",
"@lumeweb/libhyperproxy": "git+https://git.lumeweb.com/LumeWeb/libhyperproxy.git", "@lumeweb/libhyperproxy": "git+https://git.lumeweb.com/LumeWeb/libhyperproxy.git",
"@multiformats/multiaddr": "^11.6.1", "@multiformats/multiaddr": "^11.6.1",
"@scure/bip39": "^1.1.1", "@scure/bip39": "^1.2.0",
"@skynetlabs/skynet-nodejs": "^2.9.0", "@skynetlabs/skynet-nodejs": "^2.9.0",
"@types/b4a": "^1.6.0", "@types/b4a": "^1.6.0",
"@types/events": "^3.0.0", "@types/events": "^3.0.0",
"@types/node": "^18.15.3", "@types/node": "^18.15.11",
"@types/read": "^0.0.29", "@types/read": "^0.0.29",
"@types/rewire": "^2.5.28", "@types/rewire": "^2.5.28",
"@types/streamx": "^2.9.1", "@types/streamx": "^2.9.1",
@ -68,7 +72,7 @@
"cli-progress": "^3.12.0", "cli-progress": "^3.12.0",
"esbuild": "^0.14.54", "esbuild": "^0.14.54",
"http-browserify": "^1.7.0", "http-browserify": "^1.7.0",
"hyperswarm": "^4.3.7", "hyperswarm": "^4.4.0",
"interface-store": "^3.0.4", "interface-store": "^3.0.4",
"it-all": "^2.0.1", "it-all": "^2.0.1",
"it-ws": "^5.0.6", "it-ws": "^5.0.6",
@ -78,7 +82,7 @@
"os-browserify": "^0.3.0", "os-browserify": "^0.3.0",
"p-timeout": "^6.1.1", "p-timeout": "^6.1.1",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"prettier": "^2.8.4", "prettier": "^2.8.7",
"prom-client": "^14.2.0", "prom-client": "^14.2.0",
"read": "^1.0.7", "read": "^1.0.7",
"stream-browserify": "^3.0.0", "stream-browserify": "^3.0.0",

View File

@ -21,11 +21,31 @@ import { delegatedPeerRouting } from "@libp2p/delegated-peer-routing";
import { noise } from "@chainsafe/libp2p-noise"; import { noise } from "@chainsafe/libp2p-noise";
import { create as createIpfsHttpClient } from "ipfs-http-client"; import { create as createIpfsHttpClient } from "ipfs-http-client";
import { delegatedContentRouting } from "@libp2p/delegated-content-routing"; import { delegatedContentRouting } from "@libp2p/delegated-content-routing";
// @ts-ignore
import type { Options } from "ipfs-core"; import type { Options } from "ipfs-core";
import { multiaddr } from "@multiformats/multiaddr"; import { multiaddr } from "@multiformats/multiaddr";
import { DELEGATE_LIST, PROTOCOL } from "./constants.js"; import { DELEGATE_LIST, PROTOCOL } from "./constants.js";
import { ActiveQuery, addHandler, handleMessage } from "libkmodule"; import { ActiveQuery, addHandler, handleMessage } from "libkmodule";
import { createClient } from "@lumeweb/kernel-swarm-client"; import { createClient } from "@lumeweb/kernel-swarm-client";
import { ipns, ipnsValidator, ipnsSelector, IPNS } from "@helia/ipns";
import { dht, pubsub } from "@helia/ipns/routing";
import { kadDHT } from "@libp2p/kad-dht";
// @ts-ignore
import { gossipsub } from "@chainsafe/libp2p-gossipsub";
import { CID } from "multiformats/cid";
import { bases } from "multiformats/basics";
import { substr } from "runes2";
import { MultibaseDecoder } from "multiformats";
import { peerIdFromCID } from "@libp2p/peer-id";
import { bootstrap } from "@libp2p/bootstrap";
const basesByPrefix: { [prefix: string]: MultibaseDecoder<any> } = Object.keys(
bases
).reduce((acc, curr) => {
// @ts-ignore
acc[bases[curr].prefix] = bases[curr];
return acc;
}, {});
onmessage = handleMessage; onmessage = handleMessage;
@ -37,6 +57,7 @@ let moduleLoaded: Promise<void> = new Promise((resolve) => {
let swarm; let swarm;
let proxy: Proxy; let proxy: Proxy;
let fs: UnixFS; let fs: UnixFS;
let IPNS: IPNS;
// @ts-ignore // @ts-ignore
BigInt.prototype.toJSON = function () { BigInt.prototype.toJSON = function () {
@ -47,26 +68,56 @@ addHandler("presentSeed", handlePresentSeed);
addHandler("stat", handleStat); addHandler("stat", handleStat);
addHandler("ls", handleLs, { receiveUpdates: true }); addHandler("ls", handleLs, { receiveUpdates: true });
addHandler("cat", handleCat, { receiveUpdates: true }); addHandler("cat", handleCat, { receiveUpdates: true });
addHandler("ipnsResolve", handleIpnsResolve);
async function handlePresentSeed() { async function handlePresentSeed() {
swarm = createClient(); swarm = createClient();
const client = createIpfsHttpClient(getDelegateConfig()); const client = createIpfsHttpClient(getDelegateConfig());
PeerManager.instance.ipfs = await createHelia({ const libp2p = await createLibp2p({
blockstore: new MemoryBlockstore(), peerDiscovery: [
datastore: new MemoryDatastore(), bootstrap({
libp2p: await createLibp2p({ list: [
"/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
"/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
],
}),
],
transports: [hypercoreTransport({ peerManager: PeerManager.instance })], transports: [hypercoreTransport({ peerManager: PeerManager.instance })],
connectionEncryption: [noise()], connectionEncryption: [noise()],
connectionManager: {
autoDial: true,
},
streamMuxers: [yamux(), mplex()], streamMuxers: [yamux(), mplex()],
start: false, start: false,
contentRouters: [delegatedContentRouting(client)], contentRouters: [delegatedContentRouting(client)],
peerRouters: [delegatedPeerRouting(client)], peerRouters: [delegatedPeerRouting(client)],
relay: { relay: {
enabled: true,
advertise: {
enabled: false, enabled: false,
}, },
},
dht: kadDHT({
validators: {
ipns: ipnsValidator,
},
selectors: {
ipns: ipnsSelector,
},
}), }),
pubsub: gossipsub(),
});
// @ts-ignore
PeerManager.instance.ipfs = await createHelia({
blockstore: new MemoryBlockstore(),
datastore: new MemoryDatastore(),
libp2p,
}); });
proxy = new Proxy({ proxy = new Proxy({
@ -89,13 +140,18 @@ async function handlePresentSeed() {
swarm.join(PROTOCOL); swarm.join(PROTOCOL);
await swarm.start(); await swarm.start();
await swarm.ready();
// @ts-ignore // @ts-ignore
fs = unixfs(PeerManager.instance.ipfs); fs = unixfs(PeerManager.instance.ipfs);
IPNS = ipns(PeerManager.instance.ipfs as any, [
dht(PeerManager.instance.ipfs),
pubsub(PeerManager.instance.ipfs as any),
]);
moduleLoadedResolve(); moduleLoadedResolve();
} }
async function handleStat(aq: ActiveQuery) { async function handleStat(aq: ActiveQuery) {
await moduleLoaded; await ready();
if (!("cid" in aq.callerInput)) { if (!("cid" in aq.callerInput)) {
aq.reject("cid required"); aq.reject("cid required");
@ -122,7 +178,7 @@ async function handleStat(aq: ActiveQuery) {
} }
async function handleLs(aq: ActiveQuery) { async function handleLs(aq: ActiveQuery) {
await moduleLoaded; await ready();
if (!("cid" in aq.callerInput)) { if (!("cid" in aq.callerInput)) {
aq.reject("cid required"); aq.reject("cid required");
return; return;
@ -147,7 +203,7 @@ async function handleLs(aq: ActiveQuery) {
} }
async function handleCat(aq: ActiveQuery) { async function handleCat(aq: ActiveQuery) {
await moduleLoaded; await ready();
if (!("cid" in aq.callerInput)) { if (!("cid" in aq.callerInput)) {
aq.reject("cid required"); aq.reject("cid required");
@ -173,6 +229,37 @@ async function handleCat(aq: ActiveQuery) {
aq.respond(); aq.respond();
} }
async function handleIpnsResolve(aq: ActiveQuery) {
await ready();
if (!aq.callerInput || !("cid" in aq.callerInput)) {
aq.reject("cid required");
return;
}
const prefix = substr(aq.callerInput.cid, 0, 1);
if (!(prefix in basesByPrefix)) {
aq.reject("invalid multibase found in CID");
return;
}
const base = basesByPrefix[prefix];
const cid = CID.parse(aq.callerInput.cid, base);
try {
return aq.respond(
(await IPNS.resolve(peerIdFromCID(cid), aq.callerInput?.options)).asCID
);
} catch (e: any) {
aq.reject((e as Error).message);
}
}
async function ready() {
await moduleLoaded;
await PeerManager.instance.ipfsReady;
}
function getDelegateConfig(): Options { function getDelegateConfig(): Options {
const delegateString = const delegateString =
DELEGATE_LIST[Math.floor(Math.random() * DELEGATE_LIST.length)]; DELEGATE_LIST[Math.floor(Math.random() * DELEGATE_LIST.length)];