diff --git a/docs/environment-variables.md b/docs/environment-variables.md
index 1682d9e3f..679d2c5fc 100644
--- a/docs/environment-variables.md
+++ b/docs/environment-variables.md
@@ -3,29 +3,40 @@
**Warning**: the names of some of these environment variables might change at some point in the future.
This page lists the environment variables used by `ocean-node` and what effect
-they have.
-
+they have.
## Core
+
- `PRIVATE_KEY` : Private key used by this node (applies to p2p peer id, asset encryption key, etc)
-- `RPCS` : List of RPC URL for each chain. Example:
+- `RPCS` : List of RPC URL for each chain. Example:
+
```bash
export RPC="{ \"1\": \"https://rpc.eth.gateway.fm\", \"137\": \"https://polygon.meowrpc.com\", \"80001\": \"https://rpc-mumbai.maticvigil.com\" }"
```
## P2P
+
+- `P2P_ENABLE_IPV4` : Enable IPv4 conectivity. Defaults: True
+- `P2P_ENABLE_IPV6` : Enable IPv6 conectivity. Defaults: True
- `P2P_ipV4BindAddress` : Bind address for IPV4. Defaults to `0.0.0.0`
- `P2P_ipV4BindTcpPort` : Port used on IPv4 TCP connections. Defaults to `0` (Use whatever port is free. When running as docker, please set it explicitly)
- `P2P_ipV4BindWsPort` : Port used on IPv4 WS connections. Defaults to `0` (Use whatever port is free. When running as docker, please set it explicitly)
- `P2P_ipV6BindAddress` : Bind address for IPV6. Defaults to `::1`
- `P2P_ipV6BindTcpPort` : Port used on IPv6 TCP connections. Defaults to `0` (Use whatever port is free. When running as docker, please set it explicitly)
- `P2P_ipV6BindWsPort` : Port used on IPv6 WS connections. Defaults to `0` (Use whatever port is free. When running as docker, please set it explicitly)
-- `P2P_pubsubPeerDiscoveryInterval` : Interval (in ms) for discovery using pubsub. Defaults to `1000` (one second)
+- `P2P_ANNOUNCE_ADDRESSES` : List of addresses to announce to the network. Example: ["/ip4/1.2.3.4/tcp/8000"]
+- `P2P_ANNOUNCE_PRIVATE`: Announce private IPs. Default: True
+- `P2P_pubsubPeerDiscoveryInterval` : Interval (in ms) for discovery using pubsub. Defaults to `1000` (one second)
- `P2P_dhtMaxInboundStreams` : Maximum no of DHT inbound streams. Defaults to `500`
- `P2P_dhtMaxOutboundStreams` : Maximum no of DHT outbound streams. Defaults to `500`
-- `P2P_mDNSInterval` : Interval (in ms) for discovery using mDNS. Defaults to `20000` (20 seconds)
+- `P2P_mDNSInterval` : Interval (in ms) for discovery using mDNS. Defaults to `20000` (20 seconds)
- `P2P_connectionsMaxParallelDials` : Maximum no of parallel dials. Defaults to `150`
-- `P2P_connectionsDialTimeout`: Timeout for dial commands. Defaults to `10000` (10 seconds)
+- `P2P_connectionsDialTimeout`: Timeout for dial commands. Defaults to `10000` (10 seconds)
+- `P2P_ENABLE_UPNP`: Enable UPNP gateway discovery. Default: True
+- `P2P_ENABLE_AUTONAT`: Enable AutoNAT discovery. Default: True
+- `P2P_ENABLE_CIRCUIT_RELAY_SERVER`: Enable Circuit Relay Server. It will help network, but increase your bandwith usage. Should be disabled for edge nodes. Default: True
+- `P2P_ENABLE_CIRCUIT_RELAY_CLIENT`: Enable conections through relay servers. Default: True
## HTTP
-- `HTTP_API_PORT` : Port used for HTTP interface. Defaults to `8000`
\ No newline at end of file
+
+- `HTTP_API_PORT` : Port used for HTTP interface. Defaults to `8000`
diff --git a/src/@types/OceanNode.ts b/src/@types/OceanNode.ts
index e05912ef1..64f13059c 100644
--- a/src/@types/OceanNode.ts
+++ b/src/@types/OceanNode.ts
@@ -24,6 +24,8 @@ export interface OceanNodeKeys {
export interface OceanNodeP2PConfig {
bootstrapNodes: string[]
+ enableIPV4: boolean
+ enableIPV6: boolean
ipV4BindAddress: string | null
ipV4BindTcpPort: number | null
ipV4BindWsPort: number | null
@@ -36,6 +38,12 @@ export interface OceanNodeP2PConfig {
mDNSInterval: number
connectionsMaxParallelDials: number
connectionsDialTimeout: number
+ announceAddresses: string[]
+ autoNat: boolean
+ upnp: boolean
+ enableCircuitRelayServer: boolean
+ enableCircuitRelayClient: boolean
+ announcePrivateIp: boolean
}
export interface OceanNodeConfig {
diff --git a/src/components/P2P/handlers.ts b/src/components/P2P/handlers.ts
index 551560777..e4dde59cd 100644
--- a/src/components/P2P/handlers.ts
+++ b/src/components/P2P/handlers.ts
@@ -1,54 +1,2 @@
export * from './handleBroadcasts.js'
export * from './handleProtocolCommands.js'
-
-export function handlePeerConnect(details: any) {
- if (details) {
- // const peerId = details.detail
- // console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found
- /*
- try{
- this._libp2p.services.pubsub.connect(peerId.toString())
- }
- catch(e){
- console.log(e)
- console.log("Failed to connect pubsub")
- }
- */
- }
- // else{
- // console.log("Null evt ")
- // }
-}
-
-export function handlePeerDisconnect(details: any) {
- // const peerId = details.detail
- // console.log('Connection closed to:', peerId.toString()) // Emitted when a peer has been found
-}
-
-export function handlePeerDiscovery(details: any) {
- // const peerInfo = details.detail
- // console.log('Discovered new peer:', peerInfo.id.toString())
- // console.log(details.detail)
- /*
- try{
- //this._libp2p.services.pubsub.connect(peerInfo.id.toString())
- this._libp2p.services.dht.connect(peerInfo.id.toString())
- }
- catch(e){
- console.log(e)
- console.log("Failed to connect pubsub")
- }
- */
-}
-
-export function handlePeerJoined(details: any) {
- // console.log('New peer joined us:', details)
-}
-
-export function handlePeerLeft(details: any) {
- // console.log('New peer joined us:', details)
-}
-
-export function handleSubscriptionCHange(details: any) {
- // console.log('subscription-change:', details.detail)
-}
diff --git a/src/components/P2P/index.ts b/src/components/P2P/index.ts
index b1adee9b7..888300755 100644
--- a/src/components/P2P/index.ts
+++ b/src/components/P2P/index.ts
@@ -5,9 +5,9 @@ import clone from 'lodash.clonedeep'
import {
handleBroadcasts,
- handlePeerConnect,
- handlePeerDiscovery,
- handlePeerDisconnect,
+ // handlePeerConnect,
+ // handlePeerDiscovery,
+ // handlePeerDisconnect,
handleProtocolCommands
} from './handlers.js'
@@ -32,7 +32,6 @@ import { autoNAT } from '@libp2p/autonat'
import { uPnPNAT } from '@libp2p/upnp-nat'
import { ping } from '@libp2p/ping'
import { dcutr } from '@libp2p/dcutr'
-
import { kadDHT } from '@libp2p/kad-dht'
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
@@ -40,7 +39,8 @@ import { EVENTS, cidFromRawString } from '../../utils/index.js'
import { Transform } from 'stream'
import { Database } from '../database'
import { OceanNodeConfig, FindDDOResponse } from '../../@types/OceanNode'
-
+// eslint-disable-next-line camelcase
+import is_ip_private from 'private-ip'
import {
GENERIC_EMOJIS,
LOG_LEVELS_STR,
@@ -49,6 +49,7 @@ import {
import { INDEXER_DDO_EVENT_EMITTER } from '../Indexer/index.js'
import { P2P_LOGGER } from '../../utils/logging/common.js'
import { CoreHandlersRegistry } from '../core/handler/coreHandlersRegistry'
+import { multiaddr } from '@multiformats/multiaddr'
const DEFAULT_OPTIONS = {
pollInterval: 1000
@@ -110,6 +111,15 @@ export class OceanP2P extends EventEmitter {
this._topic = 'oceanprotocol'
this._libp2p = await this.createNode(this._config)
+ this._libp2p.addEventListener('peer:connect', (evt: any) => {
+ this.handlePeerConnect(evt)
+ })
+ this._libp2p.addEventListener('peer:disconnect', (evt: any) => {
+ this.handlePeerDisconnect(evt)
+ })
+ this._libp2p.addEventListener('peer:discovery', (evt: any) => {
+ this.handlePeerDiscovery(evt)
+ })
this._options = Object.assign({}, clone(DEFAULT_OPTIONS), clone(options))
this._peers = []
this._connections = {}
@@ -134,92 +144,204 @@ export class OceanP2P extends EventEmitter {
})
}
+ handlePeerConnect(details: any) {
+ if (details) {
+ const peerId = details.detail
+ P2P_LOGGER.debug('Connection established to:' + peerId.toString()) // Emitted when a peer has been found
+ try {
+ this._libp2p.services.pubsub.connect(peerId.toString())
+ } catch (e) {}
+ } else {
+ /* empty */
+ }
+ }
+
+ handlePeerDisconnect(details: any) {
+ const peerId = details.detail
+ P2P_LOGGER.debug('Connection closed to:' + peerId.toString()) // Emitted when a peer has been found
+ }
+
+ handlePeerDiscovery(details: any) {
+ const peerInfo = details.detail
+ P2P_LOGGER.debug('Discovered new peer:' + peerInfo.id.toString())
+ }
+
+ handlePeerJoined(details: any) {
+ P2P_LOGGER.debug('New peer joined us:' + details)
+ }
+
+ handlePeerLeft(details: any) {
+ P2P_LOGGER.debug('Peer left us:' + details)
+ }
+
+ handlePeerMessage(details: any) {
+ P2P_LOGGER.debug('peer joined us:' + details)
+ }
+
+ handleSubscriptionCHange(details: any) {
+ P2P_LOGGER.debug('subscription-change:' + details.detail)
+ }
+
+ shouldAnnounce(addr: any) {
+ const maddr = multiaddr(addr)
+ if (
+ this._config.p2pConfig.announcePrivateIp === false &&
+ is_ip_private(maddr.nodeAddress().address)
+ ) {
+ // disabled logs because of flooding
+ // P2P_LOGGER.debug('Deny announcment of ' + maddr.nodeAddress().address)
+ return false
+ } else {
+ // disabled logs because of flooding
+ // P2P_LOGGER.debug('Allow announcment of ' + maddr.nodeAddress().address)
+ return true
+ }
+ }
+
async createNode(config: OceanNodeConfig): Promise
{
try {
this._publicAddress = config.keys.peerId.toString()
this._publicKey = config.keys.publicKey
this._privateKey = config.keys.privateKey
-
/** @type {import('libp2p').Libp2pOptions} */
// start with some default, overwrite based on config later
- const options = {
+ let servicesConfig = {
+ identify: identify(),
+ pubsub: gossipsub({
+ allowPublishToZeroPeers: true
+ // canRelayMessage: true,
+ // enabled: true
+ }),
+ dht: kadDHT({
+ // this is necessary because this node is not connected to the public network
+ // it can be removed if, for example bootstrappers are configured
+ allowQueryWithZeroPeers: true,
+ maxInboundStreams: config.p2pConfig.dhtMaxInboundStreams,
+ maxOutboundStreams: config.p2pConfig.dhtMaxOutboundStreams,
+
+ clientMode: false, // this should be true for edge devices
+ kBucketSize: 20,
+ protocolPrefix: '/ocean/nodes/1.0.0'
+ // randomWalk: {
+ // enabled: true, // Allows to disable discovery (enabled by default)
+ // interval: 300e3,
+ // timeout: 10e3
+ // }
+ }),
+ ping: ping(),
+ dcutr: dcutr()
+ }
+ // eslint-disable-next-line no-constant-condition, no-self-compare
+ if (config.p2pConfig.enableCircuitRelayServer) {
+ servicesConfig = { ...servicesConfig, ...{ circuitRelay: circuitRelayServer() } }
+ }
+ // eslint-disable-next-line no-constant-condition, no-self-compare
+ if (config.p2pConfig.upnp) {
+ servicesConfig = { ...servicesConfig, ...{ upnpNAT: uPnPNAT() } }
+ }
+ // eslint-disable-next-line no-constant-condition, no-self-compare
+ if (config.p2pConfig.autoNat) {
+ servicesConfig = { ...servicesConfig, ...{ autoNAT: autoNAT() } }
+ }
+ const bindInterfaces = []
+ if (config.p2pConfig.enableIPV4) {
+ bindInterfaces.push(
+ `/ip4/${config.p2pConfig.ipV4BindAddress}/tcp/${config.p2pConfig.ipV4BindTcpPort}`
+ )
+ bindInterfaces.push(
+ `/ip4/${config.p2pConfig.ipV4BindAddress}/tcp/${config.p2pConfig.ipV4BindWsPort}/ws`
+ )
+ }
+ if (config.p2pConfig.enableIPV4) {
+ bindInterfaces.push(
+ `/ip6/${config.p2pConfig.ipV6BindAddress}/tcp/${config.p2pConfig.ipV6BindTcpPort}`
+ )
+ bindInterfaces.push(
+ `/ip6/${config.p2pConfig.ipV6BindAddress}/tcp/${config.p2pConfig.ipV6BindWsPort}/ws`
+ )
+ }
+ let transports = []
+ if (config.p2pConfig.enableCircuitRelayClient) {
+ transports = [
+ webSockets(),
+ tcp(),
+ circuitRelayTransport(/* {
+ discoverRelays: 2
+ } */)
+ ]
+ } else {
+ transports = [webSockets(), tcp()]
+ }
+ let options = {
addresses: {
- listen: [
- `/ip4/${config.p2pConfig.ipV4BindAddress}/tcp/${config.p2pConfig.ipV4BindTcpPort}`,
- `/ip4/${config.p2pConfig.ipV4BindAddress}/tcp/${config.p2pConfig.ipV4BindWsPort}/ws`,
- `/ip6/${config.p2pConfig.ipV6BindAddress}/tcp/${config.p2pConfig.ipV6BindTcpPort}`,
- `/ip6/${config.p2pConfig.ipV6BindAddress}/tcp/${config.p2pConfig.ipV6BindWsPort}/ws`
- ]
+ listen: bindInterfaces,
+ announceFilter: (multiaddrs: any[]) =>
+ multiaddrs.filter((m) => this.shouldAnnounce(m))
},
peerId: config.keys.peerId,
- transports: [webSockets(), tcp(), circuitRelayTransport()],
+ transports,
streamMuxers: [yamux(), mplex()],
connectionEncryption: [
noise()
// plaintext()
],
- peerDiscovery: [
- bootstrap({
- list: config.p2pConfig.bootstrapNodes
- }),
- pubsubPeerDiscovery({
- interval: config.p2pConfig.pubsubPeerDiscoveryInterval,
- topics: [
- 'oceanprotocoldiscovery',
- `oceanprotocol._peer-discovery._p2p._pubsub`, // It's recommended but not required to extend the global space
- '_peer-discovery._p2p._pubsub' // Include if you want to participate in the global space
- ],
- listenOnly: false
- }),
- mdns({
- interval: config.p2pConfig.mDNSInterval
- })
- ],
- services: {
- identify: identify(),
- pubsub: gossipsub({
- allowPublishToZeroPeers: true
- // canRelayMessage: true,
- // enabled: true
- }),
- dht: kadDHT({
- // this is necessary because this node is not connected to the public network
- // it can be removed if, for example bootstrappers are configured
- allowQueryWithZeroPeers: true,
- maxInboundStreams: config.p2pConfig.dhtMaxInboundStreams,
- maxOutboundStreams: config.p2pConfig.dhtMaxOutboundStreams,
-
- clientMode: false, // this should be true for edge devices
- kBucketSize: 20,
- protocolPrefix: '/ocean/nodes/1.0.0'
- // randomWalk: {
- // enabled: true, // Allows to disable discovery (enabled by default)
- // interval: 300e3,
- // timeout: 10e3
- // }
- }),
- autoNAT: autoNAT(),
- upnpNAT: uPnPNAT(),
- ping: ping(),
- dcutr: dcutr(),
- circuitRelay: circuitRelayServer()
- },
+ services: servicesConfig,
connectionManager: {
maxParallelDials: config.p2pConfig.connectionsMaxParallelDials, // 150 total parallel multiaddr dials
dialTimeout: config.p2pConfig.connectionsDialTimeout // 10 second dial timeout per peer dial
}
}
+ if (config.p2pConfig.bootstrapNodes && config.p2pConfig.bootstrapNodes.length > 0) {
+ options = {
+ ...options,
+ ...{
+ peerDiscovery: [
+ bootstrap({
+ list: config.p2pConfig.bootstrapNodes,
+ timeout: 1000, // in ms,
+ tagName: 'bootstrap',
+ tagValue: 50,
+ tagTTL: 10000000000
+ }),
+ mdns({
+ interval: config.p2pConfig.mDNSInterval
+ }),
+ pubsubPeerDiscovery({
+ interval: config.p2pConfig.pubsubPeerDiscoveryInterval,
+ topics: [
+ 'oceanprotocoldiscovery',
+ `oceanprotocol._peer-discovery._p2p._pubsub`, // It's recommended but not required to extend the global space
+ '_peer-discovery._p2p._pubsub' // Include if you want to participate in the global space
+ ],
+ listenOnly: false
+ })
+ ]
+ }
+ }
+ } else {
+ // only mdns & pubsubPeerDiscovery
+ options = {
+ ...options,
+ ...{
+ peerDiscovery: [
+ mdns({
+ interval: config.p2pConfig.mDNSInterval
+ }),
+ pubsubPeerDiscovery({
+ interval: config.p2pConfig.pubsubPeerDiscoveryInterval,
+ topics: [
+ 'oceanprotocoldiscovery',
+ `oceanprotocol._peer-discovery._p2p._pubsub`, // It's recommended but not required to extend the global space
+ '_peer-discovery._p2p._pubsub' // Include if you want to participate in the global space
+ ],
+ listenOnly: false
+ })
+ ]
+ }
+ }
+ }
const node = await createLibp2p(options)
await node.start()
- node.addEventListener('peer:connect', (evt: any) => {
- handlePeerConnect(evt)
- })
- node.addEventListener('peer:disconnect', (evt: any) => {
- handlePeerDisconnect(evt)
- })
- node.addEventListener('peer:discovery', (evt: any) => {
- handlePeerDiscovery(evt)
- })
// node.services.pubsub.addEventListener( 'peer joined', (evt:any) => {handlePeerJoined(evt)})
// node.services.pubsub.addEventListener('peer left', (evt:any) => {handlePeerLeft(evt)})
@@ -245,10 +367,14 @@ export class OceanP2P extends EventEmitter {
node.services.pubsub.subscribe(this._topic)
node.services.pubsub.publish(this._topic, encoding('online'))
// ;(node.services.upnpNAT as any).mapIpAddresses()
- ;(node.services.upnpNAT as any).mapIpAddresses().catch((err: any) => {
- // hole punching errors are non-fatal
- console.error(err)
- })
+ const upnpService = (node.services as any).upnpNAT
+ if (config.p2pConfig.upnp && upnpService) {
+ ;(upnpService as any).mapIpAddresses().catch((err: any) => {
+ // hole punching errors are non-fatal
+ P2P_LOGGER.info('Failed to configure UPNP Gateway(if you have one)')
+ P2P_LOGGER.debug(err)
+ })
+ }
return node
} catch (e) {
P2P_LOGGER.logMessageWithEmoji(
@@ -269,12 +395,42 @@ export class OceanP2P extends EventEmitter {
// }
}
- getPeers() {
- return this._peers.slice(0)
+ async getRunningOceanPeers() {
+ return await this.getOceanPeers()
}
- hasPeer(peer: any) {
- return Boolean(this._peers.find((p) => p.toString() === peer.toString()))
+ async getKnownOceanPeers() {
+ return await this.getOceanPeers(false, true)
+ }
+
+ async getAllOceanPeers() {
+ return await this.getOceanPeers(true, true)
+ }
+
+ async getOceanPeers(running: boolean = true, known: boolean = false) {
+ const peers: string[] = []
+
+ // get pubsub peers
+ for (const peer of this._peers.slice(0)) {
+ if (!peers.includes(peer.toString)) peers.push(peer.toString())
+ }
+ // get p2p peers and filter them by protocol
+ for (const peer of await this._libp2p.peerStore.all()) {
+ if (peer && peer.protocols) {
+ for (const protocol of peer.protocols) {
+ if (protocol === this._protocol) {
+ if (!peers.includes(peer.id.toString())) peers.push(peer.id.toString())
+ }
+ }
+ }
+ }
+
+ return peers
+ }
+
+ async hasPeer(peer: any) {
+ const s = await this._libp2p.peerStore.all()
+ return Boolean(s.find((p: any) => p.toString() === peer.toString()))
}
async broadcast(_message: any) {
@@ -390,7 +546,6 @@ export class OceanP2P extends EventEmitter {
async _pollPeers() {
const node = this._libp2p
const newPeers = (await node.services.pubsub.getSubscribers(this._topic)).sort()
-
if (this._emitChanges(newPeers)) {
const addedNew = newPeers.length > this._peers.length
this._peers = newPeers
@@ -413,8 +568,8 @@ export class OceanP2P extends EventEmitter {
differences.added.forEach((peer: any) => this.emit('peer joined', peer))
differences.removed.forEach((peer: any) => this.emit('peer left', peer))
-
- return differences.added.length > 0 || differences.removed.length > 0
+ const x = differences.added.length > 0 || differences.removed.length > 0
+ return x
}
_onMessage(event: any) {
@@ -428,14 +583,14 @@ export class OceanP2P extends EventEmitter {
async advertiseDid(did: string) {
P2P_LOGGER.logMessage('Advertising ' + did, true)
try {
- const x = this._peers.length
+ const x = (await this.getRunningOceanPeers()).length
if (x > 0) {
const cid = await cidFromRawString(did)
const multiAddrs = this._libp2p.components.addressManager.getAddresses()
// console.log('multiaddrs: ', multiAddrs)
await this._libp2p.contentRouting.provide(cid, multiAddrs)
} else {
- P2P_LOGGER.warn(
+ P2P_LOGGER.verbose(
'Could not find any Ocean peers. Nobody is listening at the moment, skipping...'
)
// save it for retry later
diff --git a/src/components/httpRoutes/getOceanPeers.ts b/src/components/httpRoutes/getOceanPeers.ts
index 156aec5fa..17ee156b7 100644
--- a/src/components/httpRoutes/getOceanPeers.ts
+++ b/src/components/httpRoutes/getOceanPeers.ts
@@ -9,7 +9,7 @@ getOceanPeersRoute.get(
'/getOceanPeers',
async (req: Request, res: Response): Promise => {
if (hasP2PInterface) {
- const peers = await req.oceanNode.getP2PNode().getPeers()
+ const peers = await req.oceanNode.getP2PNode().getRunningOceanPeers()
P2P_LOGGER.log(getDefaultLevel(), `getOceanPeers: ${peers}`, true)
res.json(peers)
} else {
diff --git a/src/test/unit/oceanP2P.test.ts b/src/test/unit/oceanP2P.test.ts
index adee3b9b5..c0b023d93 100644
--- a/src/test/unit/oceanP2P.test.ts
+++ b/src/test/unit/oceanP2P.test.ts
@@ -15,6 +15,7 @@ describe('OceanP2P Test', () => {
let node2: OceanP2P
let config1: any
let config2: any
+ const mDNSInterval: number = 1
const envOverrides = buildEnvOverrideConfig(
[
@@ -36,6 +37,11 @@ describe('OceanP2P Test', () => {
process.env.PRIVATE_KEY = process.env.NODE1_PRIVATE_KEY
config1 = await getConfiguration(true)
config1.p2pConfig.ipV4BindTcpPort = 0
+ // we don't need bootstrap nodes, we rely on Multicast DNS
+ config1.p2pConfig.mDNSInterval = mDNSInterval * 1e3
+ config1.p2pConfig.bootstrapNodes = []
+ // enable private IP
+ config1.p2pConfig.announcePrivateIp = true
node1 = new OceanP2P(config1, null)
await node1.start()
assert(node1, 'Failed to create P2P Node instance')
@@ -44,6 +50,11 @@ describe('OceanP2P Test', () => {
process.env.PRIVATE_KEY = process.env.NODE2_PRIVATE_KEY
config2 = await getConfiguration(true)
config2.p2pConfig.ipV4BindTcpPort = 0
+ // we don't need bootstrap nodes, we rely on Multicast DNS
+ config2.p2pConfig.mDNSInterval = mDNSInterval * 1e3
+ config2.p2pConfig.bootstrapNodes = []
+ // enable private IP
+ config2.p2pConfig.announcePrivateIp = true
node2 = new OceanP2P(config2, null)
await node2.start()
assert(node2, 'Failed to create P2P Node instance')
@@ -58,7 +69,7 @@ describe('OceanP2P Test', () => {
'Peer missmatch for node2'
)
})
- delay(1000)
+ delay(mDNSInterval * 1e3 * 2)
it('Start check if nodes are connected', async () => {
const allPeers1 = await node1.getAllPeerStore()
const peers1 = allPeers1.map((a: any) => a.id.toString())
@@ -74,16 +85,14 @@ describe('OceanP2P Test', () => {
)
})
it('Start check if nodes are connected with pubsub', async () => {
- let peers = await node1.getPeers()
- const peers1 = peers.map((p) => p.toString())
+ let peers = await node1.getOceanPeers()
assert(
- peers1.includes(config2.keys.peerId.toString()),
+ peers.includes(config2.keys.peerId.toString()),
'Node2 not found in node1 peer list'
)
- peers = await node2.getPeers()
- const peers2 = peers.map((p) => p.toString())
+ peers = await node2.getOceanPeers()
assert(
- peers2.includes(config1.keys.peerId.toString()),
+ peers.includes(config1.keys.peerId.toString()),
'Node1 not found in node2 peer list'
)
})
diff --git a/src/utils/config.ts b/src/utils/config.ts
index 65add4f08..a5457765d 100644
--- a/src/utils/config.ts
+++ b/src/utils/config.ts
@@ -82,6 +82,9 @@ function getSupportedChains(): RPCS | null {
return supportedNetworks
}
+function getP2PAnnounceAddresses(isStartup?: boolean): string[] {
+ return readListFromEnvVariable(ENVIRONMENT_VARIABLES.P2P_ANNOUNCE_ADDRESSES, isStartup)
+}
// valid decrypthers
function getAuthorizedDecrypters(isStartup?: boolean): string[] {
return readAddressListFromEnvVariable(
@@ -101,8 +104,8 @@ export function getAllowedAdmins(isStartup?: boolean): string[] {
return readAddressListFromEnvVariable(ENVIRONMENT_VARIABLES.ALLOWED_ADMINS, isStartup)
}
-// whenever we want to read an array of addresses from an env variable, use this common function
-function readAddressListFromEnvVariable(envVariable: any, isStartup?: boolean): string[] {
+// whenever we want to read an array of strings from an env variable, use this common function
+function readListFromEnvVariable(envVariable: any, isStartup?: boolean): string[] {
const { name } = envVariable
try {
if (!existsEnvironmentVariable(envVariable, isStartup)) {
@@ -118,7 +121,7 @@ function readAddressListFromEnvVariable(envVariable: any, isStartup?: boolean):
)
return []
}
- return addressesRaw.map((address) => getAddress(address))
+ return addressesRaw
} catch (error) {
CONFIG_LOGGER.logMessageWithEmoji(
`Missing or Invalid address(es) in ${name} env variable`,
@@ -130,6 +133,11 @@ function readAddressListFromEnvVariable(envVariable: any, isStartup?: boolean):
}
}
+// whenever we want to read an array of addresses from an env variable, use this common function
+function readAddressListFromEnvVariable(envVariable: any, isStartup?: boolean): string[] {
+ const addressesRaw: string[] = readListFromEnvVariable(envVariable, isStartup)
+ return addressesRaw.map((address) => getAddress(address))
+}
/**
* get default values for provider fee tokens
* @param supportedNetworks chains that we support
@@ -422,26 +430,29 @@ async function getEnvConfig(isStartup?: boolean): Promise {
hasP2P: interfaces.includes('P2P'),
p2pConfig: {
bootstrapNodes: [
+ // Public IPFS bootstraps
'/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
- // '/ip4/127.0.0.12/tcp/49100/p2p/12D3KooWLktGvbzuDK7gv1kS4pq6DNWxmxEREKVtBEhVFQmDNni7'
+ // OPF nodes
+ // '/dns4/node1.oceanprotocol.com/tcp/9000/p2p/'
+ '/dns4/node2.oceanprotocol.com/tcp/9000/p2p/16Uiu2HAm6u88XuC4Xke7J9NmT7qLNL4zMYEyLxqdVgAc7Rnr95o6',
+ // '/dns4/node3.oceanprotocol.com/tcp/9000/p2p/'
+ // OPF developer nodes
'/ip4/35.198.125.13/tcp/8000/p2p/16Uiu2HAmKZuuY2Lx3JiY938rJWZrYQh6kjBZCNrh3ALkodtwFRdF', // paulo
- '/ip4/34.159.64.236/tcp/8000/p2p/16Uiu2HAmAy1GcZGhzFT3cbARTmodg9c3M4EAmtBZyDgu5cSL1NPr', // jaime
+ '/ip4/35.209.77.64/tcp/8000/p2p/16Uiu2HAmFxPwhW5dmoLZnbqXFyUvr6j1PzCB1mBxRUZHGsoqQoSQ',
'/ip4/34.107.3.14/tcp/8000/p2p/16Uiu2HAm4DWmX56ZX2bKjvARJQZPMUZ9xsdtAfrMmd7P8czcN4UT', // maria
- // LOCAL
- // TODO check: we might need to have an option to use local node as a bootstrap one
- // '/ip4/127.0.0.1/tcp/8000/p2p/16Uiu2HAkuYfgjXoGcSSLSpRPD6XtUgV71t5RqmTmcqdbmrWY9MJo',
- '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
- '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
- '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
+ '/dnsaddr/ocean-node3.oceanprotocol.io/tcp/8000/p2p/16Uiu2HAm96Sx6o8XCEifPL9MtJiZCSzKqiBQApnZ6JWd7be4zwNK' // bogdan
],
+ enableIPV4: process.env.P2P_ENABLE_IPV4 !== 'false',
+ enableIPV6: process.env.P2P_ENABLE_IPV6 !== 'false',
ipV4BindAddress: getEnvValue(process.env.P2P_ipV4BindAddress, '0.0.0.0'),
ipV4BindTcpPort: getIntEnvValue(process.env.P2P_ipV4BindTcpPort, 0),
ipV4BindWsPort: getIntEnvValue(process.env.P2P_ipV4BindWsPort, 0),
ipV6BindAddress: getEnvValue(process.env.P2P_ipV6BindAddress, '::1'),
ipV6BindTcpPort: getIntEnvValue(process.env.P2P_ipV6BindTcpPort, 0),
ipV6BindWsPort: getIntEnvValue(process.env.P2P_ipV6BindWsPort, 0),
+ announceAddresses: getP2PAnnounceAddresses(isStartup),
pubsubPeerDiscoveryInterval: getIntEnvValue(
process.env.P2P_pubsubPeerDiscoveryInterval,
1000
@@ -453,7 +464,15 @@ async function getEnvConfig(isStartup?: boolean): Promise {
process.env.P2P_connectionsMaxParallelDials,
150
),
- connectionsDialTimeout: getIntEnvValue(process.env.P2P_connectionsDialTimeout, 10e3) // 10 seconds
+ connectionsDialTimeout: getIntEnvValue(
+ process.env.P2P_connectionsDialTimeout,
+ 30e3
+ ), // 10 seconds
+ upnp: process.env.P2P_ENABLE_UPNP !== 'false',
+ autoNat: process.env.P2P_ENABLE_AUTONAT !== 'false',
+ enableCircuitRelayServer: process.env.P2P_ENABLE_CIRCUIT_RELAY_SERVER !== 'false',
+ enableCircuitRelayClient: process.env.P2P_ENABLE_CIRCUIT_RELAY_CLIENT !== 'false',
+ announcePrivateIp: process.env.P2P_ANNOUNCE_PRIVATE !== 'false'
},
// Only enable provider if we have a DB_URL
hasProvider: !!getEnvValue(process.env.DB_URL, ''),
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 5bd5852f1..f10aff2b5 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -173,6 +173,12 @@ export const ENVIRONMENT_VARIABLES: Record = {
value: process.env.ADDRESS_FILE,
required: false
},
+ // p2p specific
+ P2P_ANNOUNCE_ADDRESSES: {
+ name: 'P2P_ANNOUNCE_ADDRESSES',
+ value: process.env.P2P_ANNOUNCE_ADDRESSES,
+ required: false
+ },
// node specific
NODE_ENV: { name: 'NODE_ENV', value: process.env.NODE_ENV, required: false },
AUTHORIZED_DECRYPTERS: {