mirror of
https://github.com/xtr-dev/rondevu-server.git
synced 2025-12-10 02:43:24 +00:00
feat: Implement content-based offer IDs with SHA-256 hashing
- Added hash-id.ts utility for SHA-256 content hashing
- Offer IDs now generated from hash of {sdp, topics} (sorted)
- Removed peerId from hash (inferred from authentication)
- Server generates deterministic IDs for idempotent offer creation
- Updated SQLite and D1 storage implementations
- Removed optional id field from CreateOfferRequest
- Same offer content always produces same ID
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
66
src/bloom.ts
Normal file
66
src/bloom.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Bloom filter utility for testing if peer IDs might be in a set
|
||||
* Used to filter out known peers from discovery results
|
||||
*/
|
||||
|
||||
export class BloomFilter {
|
||||
private bits: Uint8Array;
|
||||
private size: number;
|
||||
private numHashes: number;
|
||||
|
||||
/**
|
||||
* Creates a bloom filter from a base64 encoded bit array
|
||||
*/
|
||||
constructor(base64Data: string, numHashes: number = 3) {
|
||||
// Decode base64 to Uint8Array (works in both Node.js and Workers)
|
||||
const binaryString = atob(base64Data);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
for (let i = 0; i < binaryString.length; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
this.bits = bytes;
|
||||
this.size = this.bits.length * 8;
|
||||
this.numHashes = numHashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a peer ID might be in the filter
|
||||
* Returns true if possibly in set, false if definitely not in set
|
||||
*/
|
||||
test(peerId: string): boolean {
|
||||
for (let i = 0; i < this.numHashes; i++) {
|
||||
const hash = this.hash(peerId, i);
|
||||
const index = hash % this.size;
|
||||
const byteIndex = Math.floor(index / 8);
|
||||
const bitIndex = index % 8;
|
||||
|
||||
if (!(this.bits[byteIndex] & (1 << bitIndex))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple hash function (FNV-1a variant)
|
||||
*/
|
||||
private hash(str: string, seed: number): number {
|
||||
let hash = 2166136261 ^ seed;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash ^= str.charCodeAt(i);
|
||||
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
||||
}
|
||||
return hash >>> 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to parse bloom filter from base64 string
|
||||
*/
|
||||
export function parseBloomFilter(base64: string): BloomFilter | null {
|
||||
try {
|
||||
return new BloomFilter(base64);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user