-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/1982 #2051
+301
−153
Merged
Fix/1982 #2051
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
c404449
fix: getting list of sorted peers from localdb
EmiM 6279c41
feat: dial peers after replicating csrs; update peersList in localDB
EmiM d3e9009
chore: remove unused code; move libp2p closing logic to libp2p service
EmiM 1b5aae8
fix: dial only peers that haven't been dialed before
EmiM 7298e5b
Merge branch 'develop' into fix/1982
EmiM 5a7c6de
Merge branch 'develop' into fix/1982
EmiM 038a579
chore: add more logs to libp2p service
EmiM 591c4e5
chore: make ProcessInChunks a nest service
EmiM 8b3097b
fix: do not stop dial on first connection
EmiM 9940bfd
test: fix
EmiM 108bf30
chore: cleanup
EmiM 2a5f801
test: fix
EmiM 97a5652
chore: rename sortPeers
EmiM 09076fb
chore: cleanup
EmiM c64c05b
fix: test
EmiM 598df52
Merge branch 'develop' into fix/1982
EmiM 1e459c6
chore: update changelog
EmiM File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,11 @@ | ||
import { Module } from '@nestjs/common' | ||
import { SocketModule } from '../socket/socket.module' | ||
import { Libp2pService } from './libp2p.service' | ||
import { ProcessInChunksService } from './process-in-chunks.service' | ||
|
||
@Module({ | ||
imports: [SocketModule], | ||
providers: [Libp2pService], | ||
providers: [Libp2pService, ProcessInChunksService], | ||
exports: [Libp2pService], | ||
}) | ||
export class Libp2pModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,19 +9,21 @@ import { createServer } from 'it-ws' | |
import { DateTime } from 'luxon' | ||
import { EventEmitter } from 'events' | ||
import { Libp2pEvents, Libp2pNodeParams } from './libp2p.types' | ||
import { ProcessInChunks } from './process-in-chunks' | ||
import { ProcessInChunksService } from './process-in-chunks.service' | ||
import { multiaddr } from '@multiformats/multiaddr' | ||
import { ConnectionProcessInfo, PeerId, SocketActionTypes } from '@quiet/types' | ||
import { SERVER_IO_PROVIDER, SOCKS_PROXY_AGENT } from '../const' | ||
import { ServerIoProviderTypes } from '../types' | ||
import Logger from '../common/logger' | ||
import { webSockets } from '../websocketOverTor' | ||
import { all } from '../websocketOverTor/filters' | ||
import { createLibp2pAddress, createLibp2pListenAddress } from '@quiet/common' | ||
import { createLibp2pAddress, createLibp2pListenAddress, isDefined } from '@quiet/common' | ||
import { CertFieldsTypes, getReqFieldValue, loadCSR } from '@quiet/identity' | ||
import { preSharedKey } from 'libp2p/pnet' | ||
import { toString as uint8ArrayToString } from 'uint8arrays/to-string' | ||
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' | ||
import crypto from 'crypto' | ||
import { peerIdFromString } from '@libp2p/peer-id' | ||
|
||
const KEY_LENGTH = 32 | ||
export const LIBP2P_PSK_METADATA = '/key/swarm/psk/1.0.0/\n/base16/\n' | ||
|
@@ -30,15 +32,23 @@ export const LIBP2P_PSK_METADATA = '/key/swarm/psk/1.0.0/\n/base16/\n' | |
export class Libp2pService extends EventEmitter { | ||
public libp2pInstance: Libp2p | null | ||
public connectedPeers: Map<string, number> = new Map() | ||
public dialedPeers: Set<string> = new Set() | ||
// public processInChunksService: ProcessInChunks<string> | ||
private readonly logger = Logger(Libp2pService.name) | ||
constructor( | ||
@Inject(SERVER_IO_PROVIDER) public readonly serverIoProvider: ServerIoProviderTypes, | ||
@Inject(SOCKS_PROXY_AGENT) public readonly socksProxyAgent: Agent | ||
@Inject(SOCKS_PROXY_AGENT) public readonly socksProxyAgent: Agent, | ||
private readonly processInChunksService: ProcessInChunksService<string> | ||
) { | ||
super() | ||
} | ||
|
||
private dialPeer = async (peerAddress: string) => { | ||
if (this.dialedPeers.has(peerAddress)) { | ||
console.log(`Peer ${peerAddress} already dialed, not dialing`) // TODO: remove log | ||
return | ||
} | ||
this.dialedPeers.add(peerAddress) | ||
await this.libp2pInstance?.dial(multiaddr(peerAddress)) | ||
} | ||
|
||
|
@@ -79,10 +89,11 @@ export class Libp2pService extends EventEmitter { | |
libp2p = await createLibp2p({ | ||
start: false, | ||
connectionManager: { | ||
minConnections: 3, | ||
maxConnections: 8, | ||
minConnections: 3, // TODO: increase? | ||
maxConnections: 8, // TODO: increase? | ||
dialTimeout: 120_000, | ||
maxParallelDials: 10, | ||
autoDial: true, // It's a default but let's set it to have explicit information | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice idea! |
||
}, | ||
peerId: params.peerId, | ||
addresses: { | ||
|
@@ -123,43 +134,65 @@ export class Libp2pService extends EventEmitter { | |
return libp2p | ||
} | ||
|
||
// private async addPeersToPeerBook(addresses: string[]) { | ||
// for (const address of addresses) { | ||
// const peerId = multiaddr(address).getPeerId() | ||
// if (!peerId) return | ||
// // @ts-expect-error | ||
// await this.libp2pInstance?.peerStore.addressBook.add(peerIdFromString(peerId), [multiaddr(address)]) | ||
// } | ||
// } | ||
|
||
private async afterCreation(peers: string[], peerId: PeerId) { | ||
if (!this.libp2pInstance) { | ||
this.logger.error('libp2pInstance was not created') | ||
throw new Error('libp2pInstance was not created') | ||
} | ||
|
||
this.logger(`Local peerId: ${peerId.toString()}`) | ||
this.on(Libp2pEvents.DIAL_PEERS, async (addresses: string[]) => { | ||
const nonDialedAddresses = addresses.filter(peerAddress => !this.dialedPeers.has(peerAddress)) | ||
console.log('DIALING PEERS', nonDialedAddresses.length, 'addresses') | ||
this.processInChunksService.updateData(nonDialedAddresses) | ||
await this.processInChunksService.process() | ||
}) | ||
|
||
this.logger(`Initializing libp2p for ${peerId.toString()}, bootstrapping with ${peers.length} peers`) | ||
this.serverIoProvider.io.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.INITIALIZING_LIBP2P) | ||
const dialInChunks = new ProcessInChunks<string>(peers, this.dialPeer) | ||
this.processInChunksService.init(peers, this.dialPeer) | ||
|
||
this.libp2pInstance.addEventListener('peer:discovery', peer => { | ||
this.logger(`${peerId.toString()} discovered ${peer.detail.id}`) | ||
}) | ||
|
||
this.libp2pInstance.addEventListener('peer:connect', async peer => { | ||
const remotePeerId = peer.detail.remotePeer.toString() | ||
this.logger(`${peerId.toString()} connected to ${remotePeerId}`) | ||
const localPeerId = peerId.toString() | ||
this.logger(`${localPeerId} connected to ${remotePeerId}`) | ||
|
||
// Stop dialing as soon as we connect to a peer | ||
dialInChunks.stop() | ||
// this.processInChunksService.stop() | ||
|
||
this.connectedPeers.set(remotePeerId, DateTime.utc().valueOf()) | ||
this.logger(`${this.connectedPeers.size} connected peers`) | ||
this.logger(`${localPeerId} is connected to ${this.connectedPeers.size} peers`) | ||
this.logger(`${localPeerId} has ${this.libp2pInstance?.getConnections().length} open connections`) | ||
|
||
this.emit(Libp2pEvents.PEER_CONNECTED, { | ||
peers: [remotePeerId], | ||
}) | ||
const latency = await this.libp2pInstance?.ping(peer.detail.remoteAddr) | ||
this.logger(`${localPeerId} ping to ${remotePeerId}. Latency: ${latency}`) | ||
}) | ||
|
||
this.libp2pInstance.addEventListener('peer:disconnect', async peer => { | ||
const remotePeerId = peer.detail.remotePeer.toString() | ||
this.logger(`${peerId.toString()} disconnected from ${remotePeerId}`) | ||
const localPeerId = peerId.toString() | ||
this.logger(`${localPeerId} disconnected from ${remotePeerId}`) | ||
if (!this.libp2pInstance) { | ||
this.logger.error('libp2pInstance was not created') | ||
throw new Error('libp2pInstance was not created') | ||
} | ||
this.logger(`${this.libp2pInstance.getConnections().length} open connections`) | ||
this.logger(`${localPeerId} has ${this.libp2pInstance.getConnections().length} open connections`) | ||
|
||
const connectionStartTime = this.connectedPeers.get(remotePeerId) | ||
if (!connectionStartTime) { | ||
|
@@ -172,7 +205,7 @@ export class Libp2pService extends EventEmitter { | |
const connectionDuration: number = connectionEndTime - connectionStartTime | ||
|
||
this.connectedPeers.delete(remotePeerId) | ||
this.logger(`${this.connectedPeers.size} connected peers`) | ||
this.logger(`${localPeerId} is connected to ${this.connectedPeers.size} peers`) | ||
|
||
this.emit(Libp2pEvents.PEER_DISCONNECTED, { | ||
peer: remotePeerId, | ||
|
@@ -181,21 +214,16 @@ export class Libp2pService extends EventEmitter { | |
}) | ||
}) | ||
|
||
await dialInChunks.process() | ||
await this.processInChunksService.process() | ||
|
||
this.logger(`Initialized libp2p for peer ${peerId.toString()}`) | ||
} | ||
|
||
public async destroyInstance(): Promise<void> { | ||
this.libp2pInstance?.removeEventListener('peer:discovery') | ||
this.libp2pInstance?.removeEventListener('peer:connect') | ||
this.libp2pInstance?.removeEventListener('peer:disconnect') | ||
try { | ||
await this.libp2pInstance?.stop() | ||
} catch (error) { | ||
this.logger.error(error) | ||
} | ||
|
||
public async close(): Promise<void> { | ||
this.logger('Closing libp2p service') | ||
await this.libp2pInstance?.stop() | ||
this.libp2pInstance = null | ||
this.connectedPeers = new Map() | ||
this.dialedPeers = new Set() | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work with min/max connections? Once a peer has been dialed, are they never dialed again? Would that mean we might run out of peers to dial if enough peers disconnect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every dialed peer is added to libp2p's internal address book. Autodialer checks connections every X minutes. Technically (according to code) if number of connections falls below set minConnections (e.g everyone disconnect from us) autodialer should look up peers in libp2p peerStore and try to open connections again.