Skip to content

Commit 389ca40

Browse files
committed
feat(sds): add message channel with buffers and send/receive logic
This commit creates the class for an SDS message channel, including buffers for outgoing and incoming messages. Adds logic for sending messages, receiving messages, delivering messages, and reviewing acknowledgement status of messages. Also adds byte serialization for bloom filters.
1 parent a3fb1d7 commit 389ca40

11 files changed

+604
-28
lines changed

.cspell.json

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"kdfparams",
6565
"keccak",
6666
"keypair",
67+
"lamport",
6768
"lastpub",
6869
"libauth",
6970
"libp",

package-lock.json

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/proto/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ export * as proto_store from './generated/store_v3.js'
1515
export * as proto_peer_exchange from "./generated/peer_exchange.js";
1616

1717
export * as proto_metadata from './generated/metadata.js'
18+
19+
export * as proto_sds_message from './generated/sds_message.js'

packages/sds/.mocharc.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const config = {
88
'loader=ts-node/esm'
99
],
1010
exit: true,
11-
retries: 4
11+
retries: 2
1212
};
1313

1414
if (process.env.CI) {

packages/sds/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959
"node": ">=20"
6060
},
6161
"dependencies": {
62+
"@noble/hashes": "^1.7.1",
63+
"@waku/message-hash": "^0.1.17",
64+
"@waku/proto": "^0.0.8",
65+
"@waku/utils": "^0.0.21",
6266
"chai": "^5.1.2"
6367
},
6468
"devDependencies": {

packages/sds/src/bloom.spec.ts

+26-25
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { expect } from "chai";
22

3-
import { BloomFilter } from "./bloom.js";
4-
import { hashN } from "./nim_hashn/nim_hashn.mjs";
3+
import { BloomFilter, DefaultBloomFilter } from "./bloom.js";
54

65
const n = 10000;
76
const sampleChars =
@@ -20,13 +19,10 @@ describe("BloomFilter", () => {
2019
let testElements: string[];
2120

2221
beforeEach(() => {
23-
bloomFilter = new BloomFilter(
24-
{
25-
capacity: n,
26-
errorRate: 0.001
27-
},
28-
hashN
29-
);
22+
bloomFilter = new DefaultBloomFilter({
23+
capacity: n,
24+
errorRate: 0.001
25+
});
3026

3127
testElements = new Array<string>(n);
3228

@@ -55,15 +51,12 @@ describe("BloomFilter", () => {
5551
expect(bloomFilter.kHashes).to.equal(10);
5652
expect(bloomFilter.totalBits / n).to.equal(15);
5753

58-
const bloomFilter2 = new BloomFilter(
59-
{
60-
capacity: 10000,
61-
errorRate: 0.001,
62-
kHashes: 4,
63-
forceNBitsPerElem: 20
64-
},
65-
hashN
66-
);
54+
const bloomFilter2 = new DefaultBloomFilter({
55+
capacity: 10000,
56+
errorRate: 0.001,
57+
kHashes: 4,
58+
forceNBitsPerElem: 20
59+
});
6760
expect(bloomFilter2.kHashes).to.equal(4);
6861
expect(bloomFilter2.totalBits).to.equal(200000);
6962
});
@@ -107,20 +100,28 @@ describe("BloomFilter", () => {
107100
expect(bloomFilter.lookup(item)).to.equal(true);
108101
}
109102
});
103+
104+
it("should serialize and deserialize correctly", () => {
105+
const serialized = bloomFilter.toBytes();
106+
const deserialized = DefaultBloomFilter.fromBytes(
107+
serialized,
108+
bloomFilter.options
109+
);
110+
for (const item of testElements) {
111+
expect(deserialized.lookup(item)).to.equal(true);
112+
}
113+
});
110114
});
111115

112116
describe("BloomFilter with special patterns", () => {
113117
let bloomFilter: BloomFilter;
114118
const inserted: string[] = [];
115119

116120
beforeEach(() => {
117-
bloomFilter = new BloomFilter(
118-
{
119-
capacity: n,
120-
errorRate: 0.001
121-
},
122-
hashN
123-
);
121+
bloomFilter = new DefaultBloomFilter({
122+
capacity: n,
123+
errorRate: 0.001
124+
});
124125
});
125126

126127
it("should handle special patterns correctly", () => {

packages/sds/src/bloom.ts

+40
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { hashN } from "./nim_hashn/nim_hashn.mjs";
12
import { getMOverNBitsForK } from "./probabilities.js";
23

34
export interface BloomFilterOptions {
@@ -30,11 +31,15 @@ export class BloomFilter {
3031
public kHashes: number;
3132
public errorRate: number;
3233

34+
public options: BloomFilterOptions;
35+
3336
private hashN: (item: string, n: number, maxValue: number) => number;
3437
public constructor(
3538
options: BloomFilterOptions,
3639
hashN: (item: string, n: number, maxValue: number) => number
3740
) {
41+
this.options = options;
42+
3843
let nBitsPerElem: number;
3944
let k = options.kHashes ?? 0;
4045
const forceNBitsPerElem = options.forceNBitsPerElem ?? 0;
@@ -103,4 +108,39 @@ export class BloomFilter {
103108
}
104109
return true;
105110
}
111+
112+
public toBytes(): Uint8Array {
113+
const buffer = new ArrayBuffer(this.data.length * 8);
114+
const view = new DataView(buffer);
115+
for (let i = 0; i < this.data.length; i++) {
116+
view.setBigInt64(i * 8, this.data[i]);
117+
}
118+
return new Uint8Array(buffer);
119+
}
120+
121+
public static fromBytes(
122+
bytes: Uint8Array,
123+
options: BloomFilterOptions,
124+
hashN: (item: string, n: number, maxValue: number) => number
125+
): BloomFilter {
126+
const bloomFilter = new BloomFilter(options, hashN);
127+
const view = new DataView(bytes.buffer);
128+
for (let i = 0; i < bloomFilter.data.length; i++) {
129+
bloomFilter.data[i] = view.getBigUint64(i * 8, false);
130+
}
131+
return bloomFilter;
132+
}
133+
}
134+
135+
export class DefaultBloomFilter extends BloomFilter {
136+
public constructor(options: BloomFilterOptions) {
137+
super(options, hashN);
138+
}
139+
140+
public static fromBytes(
141+
bytes: Uint8Array,
142+
options: BloomFilterOptions
143+
): DefaultBloomFilter {
144+
return BloomFilter.fromBytes(bytes, options, hashN);
145+
}
106146
}

0 commit comments

Comments
 (0)