114 lines
3.6 KiB
Markdown
114 lines
3.6 KiB
Markdown
# API: hyper-p2p-bloom-gossip
|
|
|
|
**Export:** `{ HyperP2PBloomGossip, PROTOCOL }`
|
|
**Protocol:** `bloom-gossip/v1` (`PROTOCOL` constant)
|
|
|
|
## Overview
|
|
|
|
`HyperP2PBloomGossip` is a probabilistic set-membership filter backed by a fixed-size bit array and an exact `_keys` set for statistics. When a Hyperswarm `topic` is configured, peers gossip individual key insertions (`bloom-add`) so remote nodes set the same bit positions without shipping the full filter on every update.
|
|
|
|
The filter answers **“might this key have been added?”** (`mightContain`) with possible false positives and no false negatives for keys that were actually inserted on this node or learned via gossip.
|
|
|
|
## Constructor
|
|
|
|
```js
|
|
const { HyperP2PBloomGossip } = require('hyper-p2p-bloom-gossip')
|
|
const mod = new HyperP2PBloomGossip(opts)
|
|
```
|
|
|
|
| Option | Type | Default | Description |
|
|
|--------|------|---------|-------------|
|
|
| `topic` | `string` \| `Buffer` \| `null` | `null` | Hyperswarm topic; swarm joins only when set and `ready()` runs |
|
|
| `keyPair` | `KeyPair` | `hypercore-crypto.keyPair()` | Swarm identity; `peerHex` derived from public key |
|
|
| `bits` | `number` | `2048` | Bloom bit width (`_size`) |
|
|
|
|
Internal constants: `HASH_COUNT = 4` (independent FNV-derived positions per key).
|
|
|
|
## Methods
|
|
|
|
### `add(key)`
|
|
|
|
- **Parameters:** `key` — non-empty string (via `assertNonEmpty`)
|
|
- **Returns:** `true` if newly inserted; `false` if duplicate
|
|
- **Side effects:** Sets four bit positions, adds to `_keys`, increments `stats.added`, emits `add`, gossips `bloom-add` when swarm is active
|
|
|
|
### `mightContain(key)`
|
|
|
|
- **Returns:** `false` if any required bit is unset; `true` if all four positions are set (may be false positive)
|
|
- **Increments:** `stats.queries`
|
|
|
|
### `exportBits()`
|
|
|
|
Returns a serializable snapshot:
|
|
|
|
```js
|
|
{ size, hashCount, bits, count }
|
|
```
|
|
|
|
- `bits` — hex-encoded underlying `Uint8Array`
|
|
- `count` — exact key count in `_keys`
|
|
|
|
### `importBits(payload)`
|
|
|
|
Replaces the in-memory bit array from `payload.bits` (hex). Optionally updates `_size` from `payload.size`. Does not rebuild `_keys` from bits alone.
|
|
|
|
### `size()`
|
|
|
|
Exact count of keys tracked in `_keys` (not probabilistic estimate).
|
|
|
|
### `getStats()`
|
|
|
|
```js
|
|
{
|
|
added, queries, gossipIn, gossipOut,
|
|
bits, keys, protocol
|
|
}
|
|
```
|
|
|
|
### `ready()`
|
|
|
|
If `topic` is set and swarm not yet created, calls `initModuleSwarm` with protocol `bloom-gossip/v1` and `_onGossip` handler. No-op when `topic` is null.
|
|
|
|
### `close()`
|
|
|
|
Clears bits and keys, destroys swarm, emits `closed`.
|
|
|
|
## Events
|
|
|
|
| Event | Payload | When |
|
|
|-------|---------|------|
|
|
| `add` | `{ key }` | Local insert |
|
|
| `remote-add` | `{ key, peer }` | Gossip learned new key |
|
|
| `closed` | — | After `close()` |
|
|
|
|
## Gossip wire format
|
|
|
|
| `type` | Fields | Handler |
|
|
|--------|--------|---------|
|
|
| `bloom-add` | `key`, `peer`, `at` | `_onGossip` — set bits if key not in `_keys` |
|
|
|
|
Outbound gossip uses `gossipSend` from `../../_shared/p2p-bare.js` when `_peerMsgs` is wired.
|
|
|
|
## Hashing
|
|
|
|
Positions use FNV-1a style hashing (`fnvHash`) with seeds `0x811c9dc5 + i * 31` for `i ∈ [0, HASH_COUNT)`.
|
|
|
|
## Errors
|
|
|
|
- `assertNonEmpty` on `add` / `mightContain` for empty keys
|
|
- Swarm destroy errors swallowed in `close()`
|
|
|
|
## Usage notes
|
|
|
|
- Without `topic`, the module is a local bloom filter only (`_gossip` no-ops).
|
|
- For bulk reconciliation, use `exportBits` / `importBits` on a schedule separate from per-key gossip.
|
|
- False positives scale with fill ratio; default 2048 bits suits modest key counts.
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
npm install && npm test
|
|
```
|
|
|
|
See [examples/basic.js](../examples/basic.js) for a minimal local run.
|