Skip to content

Commit

Permalink
fix: circuit relay v2 follow up items
Browse files Browse the repository at this point in the history
Code sanitation:

- splits code and config into transport and server
- updates docs
- consolidates relay and circuit tests
- updates relay discovery to use topology
- increases test coverage

Bug fixes:

- if multiple relays are discovered simultaneously, try to reserve a slot in them in series, otherwise we can end up listening on multiple relays by accident
- relay server tags the reserving peer instead of tagging itself
- incoming remote address was missing `p2p-circuit` tuple so we were allowing relay to relay forwarding
- relay client tags outgoing relay connections

fixes: #1608
refs: #1610
  • Loading branch information
achingbrain committed Mar 9, 2023
1 parent 593deef commit 5d36dec
Show file tree
Hide file tree
Showing 48 changed files with 3,007 additions and 3,036 deletions.
10 changes: 3 additions & 7 deletions .aegir.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default {
const { MULTIADDRS_WEBSOCKETS } = await import('./dist/test/fixtures/browser.js')
const { plaintext } = await import('./dist/src/insecure/index.js')
const { default: Peers } = await import('./dist/test/fixtures/peers.js')
const { circuitRelayServer, circuitRelayTransport } = await import('./dist/src/circuit/index.js')

// Use the last peer
const peerId = await createFromJSON(Peers[Peers.length - 1])
Expand All @@ -28,6 +29,7 @@ export default {
},
peerId,
transports: [
circuitRelayTransport(),
webSockets()
],
streamMuxers: [
Expand All @@ -37,13 +39,7 @@ export default {
noise(),
plaintext()
],
relay: {
enabled: true,
hop: {
enabled: true,
active: false
}
},
relay: circuitRelayServer(),
nat: {
enabled: false
}
Expand Down
90 changes: 62 additions & 28 deletions doc/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- [Setup with Content and Peer Routing](#setup-with-content-and-peer-routing)
- [Setup with Relay](#setup-with-relay)
- [Setup with Automatic Reservations](#setup-with-automatic-reservations)
- [Setup with Preconfigured Reservations](#setup-with-preconfigured-reservations)
- [Setup with Keychain](#setup-with-keychain)
- [Configuring Dialing](#configuring-dialing)
- [Configuring Connection Manager](#configuring-connection-manager)
Expand Down Expand Up @@ -428,54 +429,87 @@ import { createLibp2p } from 'libp2p'
import { tcp } from '@libp2p/tcp'
import { mplex } from '@libp2p/mplex'
import { noise } from '@chainsafe/libp2p-noise'
import { circuitRelayTransport, circuitRelayServer } from 'libp2p/circuit-relay'

const node = await createLibp2p({
transports: [tcp()],
transports: [
tcp(),
circuitRelayTransport({ // allows the current node to make and accept relayed connections
discoverRelays: 0, // how many network relays to find
reservationConcurrency: 1 // how many relays to attempt to reserve slots on at once
})
],
streamMuxers: [mplex()],
connectionEncryption: [noise()],
relay: { // Circuit Relay options
enabled: true, // Allows you to dial and accept relayed connections. Does not make you a relay.
hop: {
enabled: true, // Allows you to be a relay for other peers.
timeout: 30 * 1000, // Incoming hop requests must complete within this timeout
applyConnectionLimits: true // Apply data/duration limits to relayed connections (default: true)
limit: {
duration: 120 * 1000 // the maximum amount of ms a relayed connection can be open for
data: BigInt(1 << 17) // the maximum amount of data that can be transferred over a relayed connection
}
},
advertise: {
enabled: true, // Allows you to disable advertising the Hop service
bootDelay: 15 * 60 * 1000, // Delay before HOP relay service is advertised on the network
ttl: 30 * 60 * 1000 // Delay Between HOP relay service advertisements on the network
relay: circuitRelayServer({ // makes the node function as a relay server
hopTimeout: 30 * 1000, // incoming relay requests must be resolved within this time limit
advertise: { // if set, use content routing to broadcast availability of this relay
bootDelay: 30 * 1000 // how long to wait after startup before broadcast
},
reservationManager: { // the reservation manager creates reservations on discovered relays
enabled: true, // enable the reservation manager, default: false
maxReservations: 1 // the maximum number of relays to create reservations on
reservations: {
maxReservations: 15 // how many peers are allowed to reserve relay slots on this server
reservationClearInterval: 300 * 1000 // how often to reclaim stale reservations
applyDefaultLimit: true // whether to apply default data/duration limits to each relayed connection
defaultDurationLimit: 2 * 60 * 1000 // the default maximum amount of time a relayed connection can be open for
defaultDataLimit: BigInt(2 << 7) // the default maximum number of bytes that can be transferred over a relayed connection
acl: {
// fine grained control over which peers are allow to reserve slots or connect to other peers
allowReserve: (peer: PeerId, addr: Multiaddr) => Promise<boolean>,
allowConnect: (src: PeerId, addr: Multiaddr, dst: PeerId) => Promise<AclStatus>
}
maxInboundHopStreams: 32 // how many inbound HOP streams are allow simultaneously
maxOutboundHopStreams: 64 // how many outbound HOP streams are allow simultaneously
}
}
})
})
```

#### Setup with Automatic Reservations

In this configuration the libp2p node will search the network for one relay with a free reservation slot. When it has found one and negotiated a relay reservation, the relayed address will appear in the output of `libp2p.getMultiaddrs()`.

```js
import { createLibp2p } from 'libp2p'
import { tcp } from '@libp2p/tcp'
import { mplex } from '@libp2p/mplex'
import { noise } from '@chainsafe/libp2p-noise'
import { circuitRelayTransport } from 'libp2p/circuit-relay'

const node = await createLibp2p({
transports: [tcp()],
transports: [
tcp(),
circuitRelayTransport({
discoverRelays: 1
})
],
streamMuxers: [mplex()],
connectionEncryption: [noise()]
})
```

#### Setup with Preconfigured Reservations

In this configuration the libp2p node is a circuit relay client which connects to a relay, `/ip4/123.123.123.123/p2p/QmRelay` which has been configured to have slots available.

```js
import { createLibp2p } from 'libp2p'
import { tcp } from '@libp2p/tcp'
import { mplex } from '@libp2p/mplex'
import { noise } from '@chainsafe/libp2p-noise'
import { circuitRelayTransport } from 'libp2p/circuit-relay'

const node = await createLibp2p({
transports: [
tcp(),
circuitRelayTransport()
],
addresses: {
listen: [
'/ip4/123.123.123.123/p2p/QmRelay/p2p-circuit' // a known relay node with reservation slots available
]
},
streamMuxers: [mplex()],
connectionEncryption: [noise()]
relay: { // Circuit Relay options (this config is part of libp2p core configurations)
enabled: true, // Allows you to dial and accept relayed connections. Does not make you a relay.
reservationManager: {
enabled: true, // Allows you to bind to relays with HOP enabled for improving node dialability
maxListeners: 2 // Configure maximum number of HOP relays to use
}
}
})
```

Expand Down
4 changes: 3 additions & 1 deletion examples/auto-relay/dialer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { webSockets } from '@libp2p/websockets'
import { noise } from '@chainsafe/libp2p-noise'
import { mplex } from '@libp2p/mplex'
import { multiaddr } from '@multiformats/multiaddr'
import { circuitRelayTransport } from 'libp2p/circuit-relay'

async function main () {
const autoRelayNodeAddr = process.argv[2]
Expand All @@ -12,7 +13,8 @@ async function main () {

const node = await createLibp2p({
transports: [
webSockets()
webSockets(),
circuitRelayTransport()
],
connectionEncryption: [
noise()
Expand Down
15 changes: 6 additions & 9 deletions examples/auto-relay/listener.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { webSockets } from '@libp2p/websockets'
import { noise } from '@chainsafe/libp2p-noise'
import { mplex } from '@libp2p/mplex'
import { multiaddr } from '@multiformats/multiaddr'
import { circuitRelayTransport } from 'libp2p/circuit-relay'

async function main () {
const relayAddr = process.argv[2]
Expand All @@ -12,21 +13,17 @@ async function main () {

const node = await createLibp2p({
transports: [
webSockets()
webSockets(),
circuitRelayTransport({
discoverRelays: 2
})
],
connectionEncryption: [
noise()
],
streamMuxers: [
mplex()
],
relay: {
enabled: true,
autoRelay: {
enabled: true,
maxListeners: 2
}
}
]
})

console.log(`Node started with id ${node.peerId.toString()}`)
Expand Down
11 changes: 2 additions & 9 deletions examples/auto-relay/relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createLibp2p } from 'libp2p'
import { webSockets } from '@libp2p/websockets'
import { noise } from '@chainsafe/libp2p-noise'
import { mplex } from '@libp2p/mplex'
import { circuitRelayServer } from 'libp2p/circuit-relay'

async function main () {
const node = await createLibp2p({
Expand All @@ -19,15 +20,7 @@ async function main () {
streamMuxers: [
mplex()
],
relay: {
enabled: true,
hop: {
enabled: true
},
advertise: {
enabled: true,
}
}
relay: circuitRelayServer()
})

console.log(`Node started with id ${node.peerId.toString()}`)
Expand Down
15 changes: 4 additions & 11 deletions examples/delegated-routing/src/libp2p-bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { noise } from '@chainsafe/libp2p-noise'
import { delegatedPeerRouting } from '@libp2p/delegated-peer-routing'
import { delegatedContentRouting } from '@libp2p/delegated-content-routing'
import { create as createIpfsHttpClient } from 'ipfs-http-client'
import { circuitRelayTransport } from 'libp2p/circuit-relay'

export default function Libp2pBundle ({peerInfo, peerBook}) {
const wrtcstar = new webRTCStar()
Expand All @@ -34,7 +35,8 @@ export default function Libp2pBundle ({peerInfo, peerBook}) {
],
transports: [
wrtcstar.transport,
webSockets()
webSockets(),
circuitRelayTransport()
],
streamMuxers: [
mplex()
Expand All @@ -44,15 +46,6 @@ export default function Libp2pBundle ({peerInfo, peerBook}) {
],
connectionEncryption: [
noise()
],
connectionManager: {
autoDial: false
},
relay: {
enabled: true,
hop: {
enabled: false
}
}
]
})
}
10 changes: 3 additions & 7 deletions examples/discovery-mechanisms/3.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { noise } from '@chainsafe/libp2p-noise'
import { floodsub } from '@libp2p/floodsub'
import { bootstrap } from '@libp2p/bootstrap'
import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery'
import { circuitRelayTransport, circuitRelayServer } from 'libp2p/circuit-relay'

const createNode = async (bootstrappers) => {
const node = await createLibp2p({
Expand Down Expand Up @@ -37,7 +38,7 @@ const createNode = async (bootstrappers) => {
'/ip4/0.0.0.0/tcp/0'
]
},
transports: [tcp()],
transports: [tcp(), circuitRelayTransport()],
streamMuxers: [mplex()],
connectionEncryption: [noise()],
pubsub: floodsub(),
Expand All @@ -46,12 +47,7 @@ const createNode = async (bootstrappers) => {
interval: 1000
})
],
relay: {
enabled: true, // Allows you to dial and accept relayed connections. Does not make you a relay.
hop: {
enabled: true // Allows you to be a relay for other peers
}
}
relay: circuitRelayServer()
})
console.log(`libp2p relay started with id: ${relay.peerId.toString()}`)

Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@
],
"exports": {
".": {
"types": "./src/index.d.ts",
"types": "./dist/src/index.d.ts",
"import": "./dist/src/index.js"
},
"./circuit-relay": {
"types": "./dist/src/circuit/index.d.ts",
"import": "./dist/src/circuit/index.js"
},
"./insecure": {
"types": "./dist/src/insecure/index.d.ts",
"import": "./dist/src/insecure/index.js"
Expand Down Expand Up @@ -123,6 +127,7 @@
"@libp2p/peer-id-factory": "^2.0.0",
"@libp2p/peer-record": "^5.0.0",
"@libp2p/peer-store": "^6.0.4",
"@libp2p/topology": "^4.0.1",
"@libp2p/tracked-map": "^3.0.0",
"@libp2p/utils": "^3.0.2",
"@multiformats/mafmt": "^11.0.2",
Expand All @@ -143,14 +148,15 @@
"it-map": "^2.0.0",
"it-merge": "^2.0.0",
"it-pair": "^2.0.2",
"it-pb-stream": "^3.0.0",
"it-pb-stream": "^3.2.0",
"it-pipe": "^2.0.3",
"it-sort": "^2.0.0",
"it-stream-types": "^1.0.4",
"merge-options": "^3.0.4",
"multiformats": "^11.0.0",
"p-defer": "^4.0.0",
"p-fifo": "^1.0.0",
"p-queue": "^7.3.4",
"p-retry": "^5.0.0",
"private-ip": "^3.0.0",
"protons-runtime": "^5.0.0",
Expand Down Expand Up @@ -181,7 +187,6 @@
"@libp2p/mplex": "^7.0.0",
"@libp2p/pubsub": "^6.0.0",
"@libp2p/tcp": "^6.0.0",
"@libp2p/topology": "^4.0.0",
"@libp2p/webrtc-star": "^6.0.0",
"@libp2p/websockets": "^5.0.0",
"@types/p-fifo": "^1.0.0",
Expand Down
Loading

0 comments on commit 5d36dec

Please sign in to comment.