Skip to content

Commit

Permalink
feat: create circuit relay reservations on bootstrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
2color committed Apr 26, 2024
1 parent 86462f2 commit 022b5a9
Showing 1 changed file with 85 additions and 50 deletions.
135 changes: 85 additions & 50 deletions js-peer/src/lib/libp2p.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { IDBDatastore } from 'datastore-idb'
import { createDelegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client'
import {
createDelegatedRoutingV1HttpApiClient,
DelegatedRoutingV1HttpApiClient,
} from '@helia/delegated-routing-v1-http-api-client'
import { createLibp2p, Libp2p } from 'libp2p'
import { identify } from '@libp2p/identify'
import {peerIdFromString} from '@libp2p/peer-id'
import { peerIdFromString } from '@libp2p/peer-id'
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { bootstrap } from '@libp2p/bootstrap'
Expand All @@ -13,9 +16,16 @@ import { gossipsub } from '@chainsafe/libp2p-gossipsub'
import { webSockets } from '@libp2p/websockets'
import { webTransport } from '@libp2p/webtransport'
import { webRTC, webRTCDirect } from '@libp2p/webrtc'
import { CHAT_FILE_TOPIC, CHAT_TOPIC, WEBRTC_BOOTSTRAP_PEER_ID, WEBTRANSPORT_BOOTSTRAP_PEER_ID } from './constants'
import * as filters from "@libp2p/websockets/filters"
import {
CHAT_FILE_TOPIC,
CHAT_TOPIC,
WEBRTC_BOOTSTRAP_PEER_ID,
WEBTRANSPORT_BOOTSTRAP_PEER_ID,
} from './constants'

import * as filters from '@libp2p/websockets/filters'
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
import first from 'it-first'

export async function startLibp2p() {
// enable verbose logging in browser console to view debug logs
Expand All @@ -26,38 +36,43 @@ export async function startLibp2p() {

await datastore.open()

const delegatedClient = createDelegatedRoutingV1HttpApiClient('https://delegated-ipfs.dev')
const { bootstrapAddrs, listenAddrs } = await getBootstrapMultiaddrs(delegatedClient)
console.log(bootstrapAddrs, listenAddrs)


const libp2p = await createLibp2p({
datastore,
addresses: {
listen: [
// 👇 Listen for webRTC connection
'/webrtc'
]
'/webrtc',
...listenAddrs,
],
},
transports: [
webTransport(),
webSockets(),
webRTC({
rtcConfiguration: {
iceServers: [{
// STUN servers help the browser discover its own public IPs
urls: [
'stun:stun.l.google.com:19302',
'stun:global.stun.twilio.com:3478'
]
}]
}
iceServers: [
{
// STUN servers help the browser discover its own public IPs
urls: ['stun:stun.l.google.com:19302', 'stun:global.stun.twilio.com:3478'],
},
],
},
}),
webRTCDirect(),
// 👇 Required to create circuit relay reservations in order to hole punch browser-to-browser WebRTC connections
circuitRelayTransport({
// When set to >0, this will look up the magic CID in order to discover circuit relay peers it can create a reservation with
discoverRelays: 1,
})
discoverRelays: 0,
}),
],
connectionManager: {
maxConnections: 10,
minConnections: 3
minConnections: 3,
},
connectionEncryption: [noise()],
streamMuxers: [yamux()],
Expand All @@ -66,18 +81,21 @@ export async function startLibp2p() {
},
// The app-specific go and rust peers use WebTransport and WebRTC-direct which have ephemeral multiadrrs that change.
// Thus, we dial them using only their peer id below, with delegated routing to discovery their multiaddrs
// peerDiscovery: [
// bootstrap({
// list: [
// '12D3KooWFhXabKDwALpzqMbto94sB7rvmZ6M28hs9Y9xSopDKwQr'
// WEBRTC_BOOTSTRAP_NODE,
// WEBTRANSPORT_BOOTSTRAP_NODE,
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt',
// ],
// }),
peerDiscovery: [
bootstrap({
list: bootstrapAddrs.map((maddr) => maddr.toString()),
}),
],
// [
// '12D3KooWFhXabKDwALpzqMbto94sB7rvmZ6M28hs9Y9xSopDKwQr'
// WEBRTC_BOOTSTRAP_NODE,
// WEBTRANSPORT_BOOTSTRAP_NODE,
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
// '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt',
// ],
// }),
// ],
services: {
pubsub: gossipsub({
Expand All @@ -88,23 +106,19 @@ export async function startLibp2p() {
// Delegated routing helps us discover the ephemeral multiaddrs of the dedicated go and rust bootstrap peers
// This relies on the public delegated routing endpoint https://docs.ipfs.tech/concepts/public-utilities/#delegated-routing
delegatedRouting: () => createDelegatedRoutingV1HttpApiClient('https://delegated-ipfs.dev'),
identify: identify()
identify: identify(),
},
})

libp2p.services.pubsub.subscribe(CHAT_TOPIC)
libp2p.services.pubsub.subscribe(CHAT_FILE_TOPIC)

// Try connecting to bootstrap ppers
Promise.all([
libp2p.dial(peerIdFromString(WEBRTC_BOOTSTRAP_PEER_ID)),
libp2p.dial(peerIdFromString(WEBTRANSPORT_BOOTSTRAP_PEER_ID))
])
.catch(e => {console.log('woot', e)})
// .catch((e) => {
// console.log('woot', e)
// })

libp2p.addEventListener('self:peer:update', ({ detail: { peer } }) => {
const multiaddrs = peer.addresses.map(({ multiaddr }) => multiaddr)

console.log(`changed multiaddrs: peer ${peer.id.toString()} multiaddrs: ${multiaddrs}`)
})

Expand All @@ -115,24 +129,45 @@ export async function startLibp2p() {
// every agent in network should use the same message id function
// messages could be perceived as duplicate if this isnt added (as opposed to rust peer which has unique message ids)
export async function msgIdFnStrictNoSign(msg: Message): Promise<Uint8Array> {
var enc = new TextEncoder();
var enc = new TextEncoder()

const signedMessage = msg as SignedMessage
const encodedSeqNum = enc.encode(signedMessage.sequenceNumber.toString());
const encodedSeqNum = enc.encode(signedMessage.sequenceNumber.toString())
return await sha256.encode(encodedSeqNum)
}

export const connectToMultiaddr = (libp2p: Libp2p) => async (multiaddr: Multiaddr) => {
console.log(`dialling: ${multiaddr.toString()}`)
try {
const conn = await libp2p.dial(multiaddr)
console.info('connected to', conn.remotePeer, 'on', conn.remoteAddr)
return conn
} catch (e) {
console.error(e)
throw e
}
}

export const connectToMultiaddr =
(libp2p: Libp2p) => async (multiaddr: Multiaddr) => {
console.log(`dialling: ${multiaddr.toString()}`)
try {
const conn = await libp2p.dial(multiaddr)
console.info('connected to', conn.remotePeer, 'on', conn.remoteAddr)
return conn
} catch (e) {
console.error(e)
throw e
const getBootstrapMultiaddrs = async (client: DelegatedRoutingV1HttpApiClient) => {
const peers = await Promise.all([
first(client.getPeers(peerIdFromString(WEBTRANSPORT_BOOTSTRAP_PEER_ID))),
first(client.getPeers(peerIdFromString(WEBRTC_BOOTSTRAP_PEER_ID))),
])
const bootstrapAddrs = []
const listenAddrs = []
for (const p of peers) {
if (p && p.Addrs.length > 0) {
for (const maddr of p.Addrs) {
const protos = maddr.protoNames()
if (
(protos.includes('webtransport') || protos.includes('webrtc-direct')) &&
protos.includes('certhash')
) {
bootstrapAddrs.push(maddr)
listenAddrs.push(`${maddr.toString()}/p2p/${p.ID.toString()}/p2p-circuit`)
}
}
}
}

return { bootstrapAddrs, listenAddrs }
}

0 comments on commit 022b5a9

Please sign in to comment.