Skip to content

Commit

Permalink
feat: add peer filter (#2508)
Browse files Browse the repository at this point in the history
To make filtering peers in a memory-efficient way possible, add a
peer filter based on a bloom filter using the binary representation
of the peer id.

---------

Co-authored-by: Russell Dempsey <[email protected]>
  • Loading branch information
achingbrain and SgtPooki authored Apr 26, 2024
1 parent e1923b0 commit 4afd7a9
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 1 deletion.
14 changes: 14 additions & 0 deletions packages/peer-collections/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,20 @@ const set = trackedPeerSet({ name: 'my_metric_name', metrics: libp2p.metrics })
set.add(peerId)
```

## Example - Peer filters

```TypeScript
import { peerFilter } from '@libp2p/peer-collections'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'

const peerId = await createEd25519PeerId()

const filter = peerFilter(1024)
filter.has(peerId) // false
filter.add(peerId)
filter.has(peerId) // true
```

# Install

```console
Expand Down
3 changes: 2 additions & 1 deletion packages/peer-collections/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
},
"dependencies": {
"@libp2p/interface": "^1.3.0",
"@libp2p/peer-id": "^4.1.0"
"@libp2p/peer-id": "^4.1.0",
"@libp2p/utils": "^5.3.2"
},
"devDependencies": {
"@libp2p/peer-id-factory": "^4.1.0",
Expand Down
26 changes: 26 additions & 0 deletions packages/peer-collections/src/filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { BloomFilter } from '@libp2p/utils/bloom-filter'
import type { PeerId } from '@libp2p/interface'

/**
* Uses a Bloom filter to implement a mechansim for deduplicating PeerIds in a
* way that uses a fixed amount of memory.
*/
export class PeerFilter {
private readonly filter: BloomFilter

constructor (size: number, errorRate?: number) {
this.filter = BloomFilter.create(size, errorRate)
}

has (peerId: PeerId): boolean {
return this.filter.has(peerId.toBytes())
}

add (peerId: PeerId): void {
this.filter.add(peerId.toBytes())
}
}

export function peerFilter (size: number): PeerFilter {
return new PeerFilter(size)
}
15 changes: 15 additions & 0 deletions packages/peer-collections/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,26 @@
* const set = trackedPeerSet({ name: 'my_metric_name', metrics: libp2p.metrics })
* set.add(peerId)
* ```
*
* @example Peer filters
*
* ```TypeScript
* import { peerFilter } from '@libp2p/peer-collections'
* import { createEd25519PeerId } from '@libp2p/peer-id-factory'
*
* const peerId = await createEd25519PeerId()
*
* const filter = peerFilter(1024)
* filter.has(peerId) // false
* filter.add(peerId)
* filter.has(peerId) // true
* ```
*/

export { PeerMap, peerMap } from './map.js'
export { PeerSet, peerSet } from './set.js'
export { PeerList, peerList } from './list.js'
export { PeerFilter, peerFilter } from './filter.js'

export { trackedPeerMap } from './tracked-map.js'
export { trackedPeerSet } from './tracked-set.js'
Expand Down
16 changes: 16 additions & 0 deletions packages/peer-collections/test/filter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import { expect } from 'aegir/chai'
import { PeerFilter } from '../src/index.js'

describe('peer-filter', () => {
it('should filter a peer', async () => {
const filter = new PeerFilter(1024)
const peer = await createEd25519PeerId()

expect(filter.has(peer)).to.be.false()

filter.add(peer)

expect(filter.has(peer)).to.be.true()
})
})

0 comments on commit 4afd7a9

Please sign in to comment.