Skip to content

Commit bd9d073

Browse files
committed
feat: ensure content topic is defined
Waku Messages are considered invalid if the content topic is undefined or an empty string. Avoid user error by throwing.
1 parent 6abee48 commit bd9d073

File tree

6 files changed

+137
-22
lines changed

6 files changed

+137
-22
lines changed

packages/core/src/lib/message/version_0.spec.ts

+37-6
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ describe("Waku Message version 0", function () {
88
it("Round trip binary serialization", async function () {
99
await fc.assert(
1010
fc.asyncProperty(
11-
fc.string(),
12-
fc.string(),
11+
fc.string({ minLength: 1 }),
12+
fc.string({ minLength: 1 }),
1313
fc.uint8Array({ minLength: 1 }),
1414
async (contentTopic, pubSubTopic, payload) => {
1515
const encoder = createEncoder({
@@ -37,8 +37,8 @@ describe("Waku Message version 0", function () {
3737
it("Ephemeral field set to true", async function () {
3838
await fc.assert(
3939
fc.asyncProperty(
40-
fc.string(),
41-
fc.string(),
40+
fc.string({ minLength: 1 }),
41+
fc.string({ minLength: 1 }),
4242
fc.uint8Array({ minLength: 1 }),
4343
async (contentTopic, pubSubTopic, payload) => {
4444
const encoder = createEncoder({
@@ -62,8 +62,8 @@ describe("Waku Message version 0", function () {
6262
it("Meta field set when metaSetter is specified", async function () {
6363
await fc.assert(
6464
fc.asyncProperty(
65-
fc.string(),
66-
fc.string(),
65+
fc.string({ minLength: 1 }),
66+
fc.string({ minLength: 1 }),
6767
fc.uint8Array({ minLength: 1 }),
6868
async (contentTopic, pubSubTopic, payload) => {
6969
// Encode the length of the payload
@@ -106,3 +106,34 @@ describe("Waku Message version 0", function () {
106106
);
107107
});
108108
});
109+
110+
describe("Ensures content topic is defined", () => {
111+
it("Encoder throws on undefined content topic", () => {
112+
const wrapper = function (): void {
113+
createEncoder({ contentTopic: undefined as unknown as string });
114+
};
115+
116+
expect(wrapper).to.throw("Content topic must be specified");
117+
});
118+
it("Encoder throws on empty string content topic", () => {
119+
const wrapper = function (): void {
120+
createEncoder({ contentTopic: "" });
121+
};
122+
123+
expect(wrapper).to.throw("Content topic must be specified");
124+
});
125+
it("Decoder throws on undefined content topic", () => {
126+
const wrapper = function (): void {
127+
createDecoder(undefined as unknown as string);
128+
};
129+
130+
expect(wrapper).to.throw("Content topic must be specified");
131+
});
132+
it("Decoder throws on empty string content topic", () => {
133+
const wrapper = function (): void {
134+
createDecoder("");
135+
};
136+
137+
expect(wrapper).to.throw("Content topic must be specified");
138+
});
139+
});

packages/core/src/lib/message/version_0.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ export class Encoder implements IEncoder {
7171
public contentTopic: string,
7272
public ephemeral: boolean = false,
7373
public metaSetter?: IMetaSetter
74-
) {}
74+
) {
75+
if (!contentTopic || contentTopic === "") {
76+
throw new Error("Content topic must be specified");
77+
}
78+
}
7579

7680
async toWire(message: IMessage): Promise<Uint8Array> {
7781
return proto.WakuMessage.encode(await this.toProtoObj(message));
@@ -117,7 +121,11 @@ export function createEncoder({
117121
}
118122

119123
export class Decoder implements IDecoder<DecodedMessage> {
120-
constructor(public contentTopic: string) {}
124+
constructor(public contentTopic: string) {
125+
if (!contentTopic || contentTopic === "") {
126+
throw new Error("Content topic must be specified");
127+
}
128+
}
121129

122130
fromWireToProtoObj(bytes: Uint8Array): Promise<IProtoMessage | undefined> {
123131
const protoMessage = proto.WakuMessage.decode(bytes);

packages/message-encryption/src/ecies.spec.ts

+40-6
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ describe("Ecies Encryption", function () {
99
it("Round trip binary encryption [ecies, no signature]", async function () {
1010
await fc.assert(
1111
fc.asyncProperty(
12-
fc.string(),
13-
fc.string(),
12+
fc.string({ minLength: 1 }),
13+
fc.string({ minLength: 1 }),
1414
fc.uint8Array({ minLength: 1 }),
1515
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
1616
async (pubSubTopic, contentTopic, payload, privateKey) => {
@@ -44,8 +44,8 @@ describe("Ecies Encryption", function () {
4444

4545
await fc.assert(
4646
fc.asyncProperty(
47-
fc.string(),
48-
fc.string(),
47+
fc.string({ minLength: 1 }),
48+
fc.string({ minLength: 1 }),
4949
fc.uint8Array({ minLength: 1 }),
5050
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
5151
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
@@ -86,8 +86,8 @@ describe("Ecies Encryption", function () {
8686
it("Check meta is set [ecies]", async function () {
8787
await fc.assert(
8888
fc.asyncProperty(
89-
fc.string(),
90-
fc.string(),
89+
fc.string({ minLength: 1 }),
90+
fc.string({ minLength: 1 }),
9191
fc.uint8Array({ minLength: 1 }),
9292
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
9393
async (pubSubTopic, contentTopic, payload, privateKey) => {
@@ -130,3 +130,37 @@ describe("Ecies Encryption", function () {
130130
);
131131
});
132132
});
133+
134+
describe("Ensures content topic is defined", () => {
135+
it("Encoder throws on undefined content topic", () => {
136+
const wrapper = function (): void {
137+
createEncoder({
138+
contentTopic: undefined as unknown as string,
139+
publicKey: new Uint8Array(),
140+
});
141+
};
142+
143+
expect(wrapper).to.throw("Content topic must be specified");
144+
});
145+
it("Encoder throws on empty string content topic", () => {
146+
const wrapper = function (): void {
147+
createEncoder({ contentTopic: "", publicKey: new Uint8Array() });
148+
};
149+
150+
expect(wrapper).to.throw("Content topic must be specified");
151+
});
152+
it("Decoder throws on undefined content topic", () => {
153+
const wrapper = function (): void {
154+
createDecoder(undefined as unknown as string, new Uint8Array());
155+
};
156+
157+
expect(wrapper).to.throw("Content topic must be specified");
158+
});
159+
it("Decoder throws on empty string content topic", () => {
160+
const wrapper = function (): void {
161+
createDecoder("", new Uint8Array());
162+
};
163+
164+
expect(wrapper).to.throw("Content topic must be specified");
165+
});
166+
});

packages/message-encryption/src/ecies.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ class Encoder implements IEncoder {
3737
private sigPrivKey?: Uint8Array,
3838
public ephemeral: boolean = false,
3939
public metaSetter?: IMetaSetter
40-
) {}
40+
) {
41+
if (!contentTopic || contentTopic === "") {
42+
throw new Error("Content topic must be specified");
43+
}
44+
}
4145

4246
async toWire(message: IMessage): Promise<Uint8Array | undefined> {
4347
const protoMessage = await this.toProtoObj(message);

packages/message-encryption/src/symmetric.spec.ts

+40-6
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ describe("Symmetric Encryption", function () {
99
it("Round trip binary encryption [symmetric, no signature]", async function () {
1010
await fc.assert(
1111
fc.asyncProperty(
12-
fc.string(),
13-
fc.string(),
12+
fc.string({ minLength: 1 }),
13+
fc.string({ minLength: 1 }),
1414
fc.uint8Array({ minLength: 1 }),
1515
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
1616
async (pubSubTopic, contentTopic, payload, symKey) => {
@@ -40,8 +40,8 @@ describe("Symmetric Encryption", function () {
4040
it("Round trip binary encryption [symmetric, signature]", async function () {
4141
await fc.assert(
4242
fc.asyncProperty(
43-
fc.string(),
44-
fc.string(),
43+
fc.string({ minLength: 1 }),
44+
fc.string({ minLength: 1 }),
4545
fc.uint8Array({ minLength: 1 }),
4646
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
4747
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
@@ -75,8 +75,8 @@ describe("Symmetric Encryption", function () {
7575
it("Check meta is set [symmetric]", async function () {
7676
await fc.assert(
7777
fc.asyncProperty(
78-
fc.string(),
79-
fc.string(),
78+
fc.string({ minLength: 1 }),
79+
fc.string({ minLength: 1 }),
8080
fc.uint8Array({ minLength: 1 }),
8181
fc.uint8Array({ min: 1, minLength: 32, maxLength: 32 }),
8282
async (pubSubTopic, contentTopic, payload, symKey) => {
@@ -118,3 +118,37 @@ describe("Symmetric Encryption", function () {
118118
);
119119
});
120120
});
121+
122+
describe("Ensures content topic is defined", () => {
123+
it("Encoder throws on undefined content topic", () => {
124+
const wrapper = function (): void {
125+
createEncoder({
126+
contentTopic: undefined as unknown as string,
127+
symKey: new Uint8Array(),
128+
});
129+
};
130+
131+
expect(wrapper).to.throw("Content topic must be specified");
132+
});
133+
it("Encoder throws on empty string content topic", () => {
134+
const wrapper = function (): void {
135+
createEncoder({ contentTopic: "", symKey: new Uint8Array() });
136+
};
137+
138+
expect(wrapper).to.throw("Content topic must be specified");
139+
});
140+
it("Decoder throws on undefined content topic", () => {
141+
const wrapper = function (): void {
142+
createDecoder(undefined as unknown as string, new Uint8Array());
143+
};
144+
145+
expect(wrapper).to.throw("Content topic must be specified");
146+
});
147+
it("Decoder throws on empty string content topic", () => {
148+
const wrapper = function (): void {
149+
createDecoder("", new Uint8Array());
150+
};
151+
152+
expect(wrapper).to.throw("Content topic must be specified");
153+
});
154+
});

packages/message-encryption/src/symmetric.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ class Encoder implements IEncoder {
3232
private sigPrivKey?: Uint8Array,
3333
public ephemeral: boolean = false,
3434
public metaSetter?: IMetaSetter
35-
) {}
35+
) {
36+
if (!contentTopic || contentTopic === "") {
37+
throw new Error("Content topic must be specified");
38+
}
39+
}
3640

3741
async toWire(message: IMessage): Promise<Uint8Array | undefined> {
3842
const protoMessage = await this.toProtoObj(message);

0 commit comments

Comments
 (0)