Skip to content

Commit 4afd7a9

Browse files
feat: add peer filter (#2508)
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]>
1 parent e1923b0 commit 4afd7a9

File tree

5 files changed

+73
-1
lines changed

5 files changed

+73
-1
lines changed

packages/peer-collections/README.md

+14
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,20 @@ const set = trackedPeerSet({ name: 'my_metric_name', metrics: libp2p.metrics })
108108
set.add(peerId)
109109
```
110110

111+
## Example - Peer filters
112+
113+
```TypeScript
114+
import { peerFilter } from '@libp2p/peer-collections'
115+
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
116+
117+
const peerId = await createEd25519PeerId()
118+
119+
const filter = peerFilter(1024)
120+
filter.has(peerId) // false
121+
filter.add(peerId)
122+
filter.has(peerId) // true
123+
```
124+
111125
# Install
112126

113127
```console

packages/peer-collections/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
},
5656
"dependencies": {
5757
"@libp2p/interface": "^1.3.0",
58-
"@libp2p/peer-id": "^4.1.0"
58+
"@libp2p/peer-id": "^4.1.0",
59+
"@libp2p/utils": "^5.3.2"
5960
},
6061
"devDependencies": {
6162
"@libp2p/peer-id-factory": "^4.1.0",
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { BloomFilter } from '@libp2p/utils/bloom-filter'
2+
import type { PeerId } from '@libp2p/interface'
3+
4+
/**
5+
* Uses a Bloom filter to implement a mechansim for deduplicating PeerIds in a
6+
* way that uses a fixed amount of memory.
7+
*/
8+
export class PeerFilter {
9+
private readonly filter: BloomFilter
10+
11+
constructor (size: number, errorRate?: number) {
12+
this.filter = BloomFilter.create(size, errorRate)
13+
}
14+
15+
has (peerId: PeerId): boolean {
16+
return this.filter.has(peerId.toBytes())
17+
}
18+
19+
add (peerId: PeerId): void {
20+
this.filter.add(peerId.toBytes())
21+
}
22+
}
23+
24+
export function peerFilter (size: number): PeerFilter {
25+
return new PeerFilter(size)
26+
}

packages/peer-collections/src/index.ts

+15
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,26 @@
8484
* const set = trackedPeerSet({ name: 'my_metric_name', metrics: libp2p.metrics })
8585
* set.add(peerId)
8686
* ```
87+
*
88+
* @example Peer filters
89+
*
90+
* ```TypeScript
91+
* import { peerFilter } from '@libp2p/peer-collections'
92+
* import { createEd25519PeerId } from '@libp2p/peer-id-factory'
93+
*
94+
* const peerId = await createEd25519PeerId()
95+
*
96+
* const filter = peerFilter(1024)
97+
* filter.has(peerId) // false
98+
* filter.add(peerId)
99+
* filter.has(peerId) // true
100+
* ```
87101
*/
88102

89103
export { PeerMap, peerMap } from './map.js'
90104
export { PeerSet, peerSet } from './set.js'
91105
export { PeerList, peerList } from './list.js'
106+
export { PeerFilter, peerFilter } from './filter.js'
92107

93108
export { trackedPeerMap } from './tracked-map.js'
94109
export { trackedPeerSet } from './tracked-set.js'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
2+
import { expect } from 'aegir/chai'
3+
import { PeerFilter } from '../src/index.js'
4+
5+
describe('peer-filter', () => {
6+
it('should filter a peer', async () => {
7+
const filter = new PeerFilter(1024)
8+
const peer = await createEd25519PeerId()
9+
10+
expect(filter.has(peer)).to.be.false()
11+
12+
filter.add(peer)
13+
14+
expect(filter.has(peer)).to.be.true()
15+
})
16+
})

0 commit comments

Comments
 (0)