Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0a807c1
packages, node-version, api changes libp2p v3
giurgiur99 Dec 17, 2025
4526d5d
lint fix
giurgiur99 Dec 17, 2025
41c138a
fix peer id key generation
giurgiur99 Dec 17, 2025
67c9be9
fix crypt
giurgiur99 Dec 17, 2025
cf42c04
fix integration assert
giurgiur99 Dec 17, 2025
1979209
use v20 for system tests
giurgiur99 Dec 17, 2025
40c1fc2
back to 22.5.1 ci
giurgiur99 Dec 17, 2025
5a24f4d
try force reload config
giurgiur99 Dec 18, 2025
915927c
Revert "try force reload config"
giurgiur99 Dec 18, 2025
334798e
equal check
giurgiur99 Dec 18, 2025
bdf9f2f
log ddo
giurgiur99 Dec 18, 2025
1f8d2c8
run all tests
giurgiur99 Dec 18, 2025
7768c7b
new instantce
giurgiur99 Dec 18, 2025
add6445
Revert "new instantce"
giurgiur99 Dec 18, 2025
bb377b2
log test
giurgiur99 Dec 18, 2025
1eff4bc
logs
giurgiur99 Dec 18, 2025
3d82d28
use correct ddo
giurgiur99 Dec 18, 2025
285dc08
revert changes
giurgiur99 Dec 18, 2025
f7dfe2c
force refresh config
giurgiur99 Dec 18, 2025
3a308e0
change order
giurgiur99 Dec 19, 2025
d08d638
remove logs
giurgiur99 Dec 19, 2025
5282ca6
tear down envs after tests
giurgiur99 Dec 19, 2025
953c65f
tear down
giurgiur99 Dec 19, 2025
4a25e77
new instance
giurgiur99 Dec 19, 2025
865f324
restart indexer
giurgiur99 Jan 5, 2026
193d365
skip db checks
giurgiur99 Jan 5, 2026
6d19c81
global check threads
giurgiur99 Jan 5, 2026
30098e9
cleanup
giurgiur99 Jan 5, 2026
79f1f67
revert p2p changes
giurgiur99 Jan 5, 2026
a701ce4
Revert "revert p2p changes"
giurgiur99 Jan 5, 2026
9555c61
Merge branch 'main' into p2p-v3
giurgiur99 Jan 6, 2026
afb8e09
custom dial logic
giurgiur99 Jan 6, 2026
65e01bd
Merge branch 'main' into p2p-v3
giurgiur99 Jan 6, 2026
9574285
event target and close connection
giurgiur99 Jan 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,437 changes: 855 additions & 1,582 deletions package-lock.json

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,25 @@
"changelog": "auto-changelog -p"
},
"dependencies": {
"@chainsafe/libp2p-noise": "^15.1.0",
"@chainsafe/libp2p-yamux": "^6.0.2",
"@chainsafe/libp2p-noise": "^17.0.0",
"@chainsafe/libp2p-yamux": "^8.0.1",
"@elastic/elasticsearch": "^8.14.0",
"@libp2p/autonat": "^2.0.0",
"@libp2p/bootstrap": "^10.1.1",
"@libp2p/circuit-relay-v2": "^1.1.1",
"@libp2p/crypto": "^4.1.5",
"@libp2p/dcutr": "^1.1.1",
"@libp2p/identify": "^2.1.1",
"@libp2p/kad-dht": "^12.1.1",
"@libp2p/mdns": "^10.1.1",
"@libp2p/peer-id": "^4.1.4",
"@libp2p/peer-id-factory": "^4.1.4",
"@libp2p/ping": "^1.1.1",
"@libp2p/pubsub": "^9.0.22",
"@libp2p/pubsub-peer-discovery": "^10.0.2",
"@libp2p/tcp": "^9.1.1",
"@libp2p/upnp-nat": "^1.2.1",
"@libp2p/websockets": "^8.1.1",
"@libp2p/autonat": "^3.0.9",
"@libp2p/bootstrap": "^12.0.10",
"@libp2p/circuit-relay-v2": "^4.1.2",
"@libp2p/crypto": "^5.1.13",
"@libp2p/dcutr": "^3.0.9",
"@libp2p/identify": "^4.0.9",
"@libp2p/kad-dht": "^16.1.2",
"@libp2p/mdns": "^12.0.10",
"@libp2p/peer-id": "^6.0.4",
"@libp2p/peer-id-factory": "^4.2.4",
"@libp2p/ping": "^3.0.9",
"@libp2p/pubsub": "^10.1.18",
"@libp2p/pubsub-peer-discovery": "^12.0.0",
"@libp2p/tcp": "^11.0.9",
"@libp2p/upnp-nat": "^4.0.9",
"@libp2p/websockets": "^10.1.2",
"@multiformats/multiaddr": "^10.2.0",
"@oceanprotocol/contracts": "^2.5.0",
"@oceanprotocol/ddo-js": "^0.1.4",
Expand All @@ -85,7 +85,7 @@
"ipaddr.js": "^2.3.0",
"it-pipe": "^3.0.1",
"jsonwebtoken": "^9.0.2",
"libp2p": "^1.8.0",
"libp2p": "^3.1.2",
"lodash": "^4.17.21",
"lzma-purejs-requirejs": "^1.0.0",
"node-cron": "^3.0.3",
Expand Down
120 changes: 73 additions & 47 deletions src/components/P2P/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import { noise } from '@chainsafe/libp2p-noise'
import { mdns } from '@libp2p/mdns'
import { yamux } from '@chainsafe/libp2p-yamux'
import { peerIdFromString } from '@libp2p/peer-id'
import { pipe } from 'it-pipe'
// import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery'

import { tcp } from '@libp2p/tcp'
import { webSockets } from '@libp2p/websockets'
import { circuitRelayTransport, circuitRelayServer } from '@libp2p/circuit-relay-v2'
import { createLibp2p, Libp2p } from 'libp2p'
import type { AddressManager, TransportManager } from '@libp2p/interface-internal'
import { identify, identifyPush } from '@libp2p/identify'
import { autoNAT } from '@libp2p/autonat'
import { uPnPNAT } from '@libp2p/upnp-nat'
Expand Down Expand Up @@ -61,7 +61,7 @@ type DDOCache = {
let index = 0

export class OceanP2P extends EventEmitter {
_libp2p: any
_libp2p: Libp2p
_topic: string
_options: any
_peers: any[]
Expand Down Expand Up @@ -162,6 +162,22 @@ export class OceanP2P extends EventEmitter {
try {
const peerInfo = details.detail
P2P_LOGGER.debug('Discovered new peer:' + peerInfo.id.toString())

// v2/v3: autodialer was removed - we implement custom dial logic
const currentConnections = this._libp2p.getConnections().length
const { minConnections, maxConnections } = this._config.p2pConfig

// Only dial if we're below minConnections or have room for more
if (currentConnections < minConnections || currentConnections < maxConnections) {
const existingConnections = this._libp2p.getConnections(peerInfo.id)
if (existingConnections.length === 0) {
this._libp2p.dial(peerInfo.id).catch((err: Error) => {
P2P_LOGGER.debug(
`Failed to dial discovered peer ${peerInfo.id}: ${err.message}`
)
})
}
}
} catch (e) {
// no panic if it failed
// console.error(e)
Expand Down Expand Up @@ -234,7 +250,7 @@ export class OceanP2P extends EventEmitter {
P2P_LOGGER.info(`Starting P2P Node with peerID: ${this._publicAddress}`)

this._publicKey = config.keys.publicKey
this._privateKey = config.keys.privateKey
this._privateKey = config.keys.privateKey.raw
/** @type {import('libp2p').Libp2pOptions} */
// start with some default, overwrite based on config later
const bindInterfaces = []
Expand Down Expand Up @@ -337,33 +353,24 @@ export class OceanP2P extends EventEmitter {

let transports = []
P2P_LOGGER.info('Enabling P2P Transports: websockets, tcp, circuitRelay')
transports = [
webSockets(),
tcp(),
circuitRelayTransport({
discoverRelays: config.p2pConfig.circuitRelays
})
]
// relay discovery is now automatic through the network's RandomWalk component
transports = [webSockets(), tcp(), circuitRelayTransport()]

let options = {
addresses,
peerId: config.keys.peerId,
privateKey: config.keys.privateKey,
transports,
streamMuxers: [yamux()],
connectionEncryption: [
connectionEncrypters: [
noise()
// plaintext()
],
services: servicesConfig,
connectionManager: {
maxParallelDials: config.p2pConfig.connectionsMaxParallelDials, // 150 total parallel multiaddr dials
dialTimeout: config.p2pConfig.connectionsDialTimeout, // 10 second dial timeout per peer dial
minConnections: config.p2pConfig.minConnections,
maxParallelDials: config.p2pConfig.connectionsMaxParallelDials,
dialTimeout: config.p2pConfig.connectionsDialTimeout,
maxConnections: config.p2pConfig.maxConnections,
autoDialPeerRetryThreshold: config.p2pConfig.autoDialPeerRetryThreshold,
autoDialConcurrency: config.p2pConfig.autoDialConcurrency,
maxPeerAddrsToDial: config.p2pConfig.maxPeerAddrsToDial,
autoDialInterval: config.p2pConfig.autoDialInterval
maxPeerAddrsToDial: config.p2pConfig.maxPeerAddrsToDial
}
}
if (config.p2pConfig.bootstrapNodes && config.p2pConfig.bootstrapNodes.length > 0) {
Expand Down Expand Up @@ -443,13 +450,23 @@ export class OceanP2P extends EventEmitter {
// }
}

async getNetworkingStats() {
getNetworkingStats() {
const ret: any = {}
ret.binds = await this._libp2p.components.addressManager.getListenAddrs()
ret.listen = await this._libp2p.components.transportManager.getAddrs()
ret.observing = await this._libp2p.components.addressManager.getObservedAddrs()
ret.announce = await this._libp2p.components.addressManager.getAnnounceAddrs()
ret.connections = await this._libp2p.getConnections()
ret.announce = this._libp2p.getMultiaddrs()
ret.connections = this._libp2p.getConnections()

const libp2pInternal = this._libp2p as Libp2p & {
components: {
addressManager: AddressManager
transportManager: TransportManager
}
}
if (libp2pInternal.components) {
ret.binds = libp2pInternal.components.addressManager.getListenAddrs()
ret.listen = libp2pInternal.components.transportManager.getAddrs()
ret.observing = libp2pInternal.components.addressManager.getObservedAddrs()
}

return ret
}

Expand Down Expand Up @@ -506,11 +523,9 @@ export class OceanP2P extends EventEmitter {
// UPDATE: no need to slice 4 bytes here, actually we need those on client side to verify the node id and perform the encryption of the keys + iv
// See config.ts => getPeerIdFromPrivateKey()

const pubKey = Buffer.from(peerId.publicKey).toString('hex') // no need to do .subarray(4).toString('hex')
const pubKey = Buffer.from(peerId.publicKey.raw).toString('hex') // no need to do .subarray(4).toString('hex')
const peer = await this._libp2p.peerStore.get(peerId)

// write the publicKey as well
peer.publicKey = pubKey
// Note: this is a 'compressed' version of the publicKey, we need to decompress it on client side (not working with bellow attempts)
// otherwise the encryption will fail due to public key size mismatch

Expand All @@ -519,7 +534,10 @@ export class OceanP2P extends EventEmitter {
// Buffer.from(decompressedKey).toString('hex')
// in any case is not working (it crashes here)

return peer
return {
...peer,
publicKey: pubKey
}
} catch (e) {
return null
}
Expand All @@ -545,7 +563,8 @@ export class OceanP2P extends EventEmitter {
})
if (peerData) {
for (const x of peerData.addresses) {
multiaddrs.push(x.multiaddr)
// v3: Convert to local Multiaddr type to avoid type mismatch
multiaddrs.push(multiaddr(x.multiaddr.toString()))
}
}
} catch (e) {
Expand All @@ -560,7 +579,8 @@ export class OceanP2P extends EventEmitter {
})
if (peerData) {
for (const index in peerData.multiaddrs) {
multiaddrs.push(peerData.multiaddrs[index])
// v3: Convert to local Multiaddr type to avoid type mismatch
multiaddrs.push(multiaddr(peerData.multiaddrs[index].toString()))
}
}
} catch (e) {
Expand Down Expand Up @@ -622,7 +642,7 @@ export class OceanP2P extends EventEmitter {
status: { httpStatus: 200, error: '' },
stream: null
}
let peerId: any
let peerId
try {
peerId = peerIdFromString(peerName)
} catch (e) {
Expand All @@ -644,7 +664,7 @@ export class OceanP2P extends EventEmitter {
} else {
// just used what we were instructed to use
for (const addr of multiAddrs) {
multiaddrs.push(new Multiaddr(addr))
multiaddrs.push(multiaddr(addr))
}
}
if (multiaddrs.length < 1) {
Expand All @@ -660,9 +680,9 @@ export class OceanP2P extends EventEmitter {
const options = {
signal: AbortSignal.timeout(10000),
priority: 100,
runOnTransientConnection: true
runOnLimitedConnection: true
}
const connection = await this._libp2p.dial(multiaddrs, options)
const connection = await this._libp2p.dial(peerId, options)
if (connection.remotePeer.toString() !== peerId.toString()) {
response.status.httpStatus = 404
response.status.error = `Invalid peer on the other side: ${connection.remotePeer.toString()}`
Expand All @@ -678,18 +698,19 @@ export class OceanP2P extends EventEmitter {
}

if (stream) {
// @ts-ignore libp2p v3 Stream type differs from Node.js Stream
response.stream = stream
try {
await pipe(
// Source data
[uint8ArrayFromString(message)],
// Write to the stream, and pass its output to the next function
stream,
// this is the anayze function
// doubler as any,
// Sink function
sink
)
// v3: Use EventTarget stream API
// Send the message
stream.send(uint8ArrayFromString(message))
// Close write side to signal end of message (v1 receivers wait for stream to end)
// v3 close() closes writes but keeps readable until remote also closes
await stream.close()

// Pass stream data to sink function (for response handling)
// v3 streams are still AsyncIterable
await sink(stream)
} catch (err) {
P2P_LOGGER.error(
`Cannot connect to peer - Unable to send P2P message: ${err.message}`
Expand Down Expand Up @@ -781,8 +802,9 @@ export class OceanP2P extends EventEmitter {
P2P_LOGGER.debug('Advertising "' + did + `" as CID:` + cid)
const x = (await this.getAllOceanPeers()).length
if (x > 0) {
const multiAddrs = this._libp2p.components.addressManager.getAddresses()
const multiAddrs = this._libp2p.getMultiaddrs()
// console.log('multiaddrs: ', multiAddrs)
// @ts-ignore ignore the type mismatch
this._libp2p.contentRouting.provide(cid, multiAddrs).catch((err: any) => {
P2P_LOGGER.error(`Error advertising DDO: ${err}`)
})
Expand Down Expand Up @@ -832,6 +854,7 @@ export class OceanP2P extends EventEmitter {
const cid = await cidFromRawString(input)
const peersFound = []
try {
// @ts-ignore ignore the type mismatch
const f = await this._libp2p.contentRouting.findProviders(cid, {
queryFuncTimeout: timeout || 20000 // 20 seconds
// on timeout the query ends with an abort signal => CodeError: Query aborted
Expand All @@ -842,7 +865,10 @@ export class OceanP2P extends EventEmitter {
} catch (e) {
P2P_LOGGER.error('getProvidersForString()' + e.message)
}
return peersFound
return peersFound.map((peer) => ({
id: peer.id.toString(),
multiaddrs: peer.multiaddrs
}))
}

// cache a ddos object
Expand Down
2 changes: 1 addition & 1 deletion src/components/core/handler/downloadHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export async function handleDownloadUrlCommand(
// we parse the string into the object again
const encryptedObject = ethCrypto.cipher.parse(task.aes_encrypted_key)
// get the key from configuration
const nodePrivateKey = Buffer.from(config.keys.privateKey).toString('hex')
const nodePrivateKey = Buffer.from(config.keys.privateKey.raw).toString('hex')
const decrypted = await ethCrypto.decryptWithPrivateKey(
nodePrivateKey,
encryptedObject
Expand Down
2 changes: 1 addition & 1 deletion src/components/core/handler/p2p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class GetP2PNetworkStatsHandler extends CommandHandler {
try {
const config = await getConfiguration()
if (config.p2pConfig.enableNetworkStats) {
const stats = await this.getOceanNode().getP2PNode().getNetworkingStats()
const stats = this.getOceanNode().getP2PNode().getNetworkingStats()
return {
stream: Readable.from(JSON.stringify(stats, null, 4)),
status: { httpStatus: 200 }
Expand Down
4 changes: 2 additions & 2 deletions src/components/core/utils/feesHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,15 +452,15 @@ export async function checkFee(
*/
export async function getProviderWallet(chainId?: string): Promise<ethers.Wallet> {
return new ethers.Wallet(
Buffer.from((await getConfiguration()).keys.privateKey).toString('hex')
Buffer.from((await getConfiguration()).keys.privateKey.raw).toString('hex')
)
}
export async function getProviderWalletAddress(): Promise<string> {
return (await getProviderWallet()).address
}

export async function getProviderKey(): Promise<string> {
return Buffer.from((await getConfiguration()).keys.privateKey).toString('hex')
return Buffer.from((await getConfiguration()).keys.privateKey.raw).toString('hex')
}

/**
Expand Down
Loading
Loading