make adjustments to the types and bring back prev implementation

This commit is contained in:
weboko 2023-01-31 00:37:55 +01:00
parent 46e6d732e2
commit 847599a6f7
No known key found for this signature in database

View File

@ -1,18 +1,22 @@
import debug from "debug"; import debug from "debug";
import { DecodedMessage, Decoder, Encoder, proto } from "@waku/core/lib/message/version_0"; import { DecodedMessage, Decoder, Encoder, proto } from "@waku/core/lib/message/version_0";
import { IEncoder, IDecoder, IDecodedMessage, IProtoMessage, IMessage } from "@waku/interfaces";
import { WakuMessage } from "@waku/proto";
import { HandshakeResult, HandshakeStepResult } from "./handshake.js"; import { HandshakeResult, HandshakeStepResult } from "./handshake.js";
import { PayloadV2 } from "./payload.js"; import { PayloadV2 } from "./payload.js";
const log = debug("waku:message:noise-codec"); const log = debug("waku:message:noise-codec");
const OneMillion = BigInt(1_000_000);
// WakuMessage version for noise protocol // WakuMessage version for noise protocol
const version = 2; const version = 2;
/** /**
* Used internally in the pairing object to represent a handshake message * Used internally in the pairing object to represent a handshake message
*/ */
export class NoiseHandshakeMessage extends DecodedMessage { export class NoiseHandshakeMessage extends DecodedMessage implements IDecodedMessage {
get payloadV2(): PayloadV2 { get payloadV2(): PayloadV2 {
if (!this.payload) throw new Error("no payload available"); if (!this.payload) throw new Error("no payload available");
return PayloadV2.deserialize(this.payload); return PayloadV2.deserialize(this.payload);
@ -23,13 +27,38 @@ export class NoiseHandshakeMessage extends DecodedMessage {
* Used in the pairing object for encoding the messages exchanged * Used in the pairing object for encoding the messages exchanged
* during the handshake process * during the handshake process
*/ */
export class NoiseHandshakeEncoder extends Encoder { export class NoiseHandshakeEncoder implements IEncoder {
/** /**
* @param contentTopic content topic on which the encoded WakuMessages will be sent * @param contentTopic content topic on which the encoded WakuMessages will be sent
* @param hsStepResult the result of a step executed while performing the handshake process * @param hsStepResult the result of a step executed while performing the handshake process
* @param ephemeral makes messages ephemeral in the Waku network
*/ */
constructor(public contentTopic: string, private hsStepResult: HandshakeStepResult) { constructor(public contentTopic: string, private hsStepResult: HandshakeStepResult, public ephemeral: boolean = true) {}
super(contentTopic);
async toWire(message: IMessage): Promise<Uint8Array | undefined> {
return this.encode(message);
}
async toProtoObj(message: IMessage): Promise<IProtoMessage | undefined> {
return this.encodeProto(message);
}
async encode(message: IMessage): Promise<Uint8Array | undefined> {
const protoMessage = await this.encodeProto(message);
if (!protoMessage) return;
return WakuMessage.encode(protoMessage);
}
async encodeProto(message: IMessage): Promise<IProtoMessage | undefined> {
const timestamp = message.timestamp ?? new Date();
return {
ephemeral: this.ephemeral,
rateLimitProof: undefined,
payload: this.hsStepResult.payload2.serialize(),
version: version,
contentTopic: this.contentTopic,
timestamp: BigInt(timestamp.valueOf()) * OneMillion,
};
} }
} }
@ -37,15 +66,27 @@ export class NoiseHandshakeEncoder extends Encoder {
* Used in the pairing object for decoding the messages exchanged * Used in the pairing object for decoding the messages exchanged
* during the handshake process * during the handshake process
*/ */
export class NoiseHandshakeDecoder extends Decoder { export class NoiseHandshakeDecoder implements IDecoder<NoiseHandshakeMessage> {
/** /**
* @param contentTopic content topic on which the encoded WakuMessages were sent * @param contentTopic content topic on which the encoded WakuMessages were sent
*/ */
constructor(public contentTopic: string) { constructor(public contentTopic: string) {}
super(contentTopic);
fromProtoObj(proto: IProtoMessage): Promise<NoiseHandshakeMessage | undefined> {
return this.decode(proto);
}
fromWireToProtoObj(bytes: Uint8Array): Promise<IProtoMessage | undefined> {
return this.decodeProto(bytes);
} }
async fromProtoObj(proto: proto.WakuMessage): Promise<NoiseHandshakeMessage | undefined> { decodeProto(bytes: Uint8Array): Promise<IProtoMessage | undefined> {
const protoMessage = WakuMessage.decode(bytes);
log("Message decoded", protoMessage);
return Promise.resolve(protoMessage as IProtoMessage);
}
async decode(proto: IProtoMessage): Promise<NoiseHandshakeMessage | undefined> {
// https://github.com/status-im/js-waku/issues/921 // https://github.com/status-im/js-waku/issues/921
if (proto.version === undefined) { if (proto.version === undefined) {
proto.version = 0; proto.version = 0;
@ -69,7 +110,18 @@ export class NoiseHandshakeDecoder extends Decoder {
* Represents a secure message. These are messages that are transmitted * Represents a secure message. These are messages that are transmitted
* after a successful handshake is performed. * after a successful handshake is performed.
*/ */
export class NoiseSecureMessage extends DecodedMessage {} export class NoiseSecureMessage extends DecodedMessage implements IDecodedMessage {
private readonly _decodedPayload: Uint8Array;
constructor(proto: WakuMessage, decodedPayload: Uint8Array) {
super(proto);
this._decodedPayload = decodedPayload;
}
get payload(): Uint8Array {
return this._decodedPayload;
}
}
/** /**
* js-waku encoder for secure messages. After a handshake is successful, a * js-waku encoder for secure messages. After a handshake is successful, a
@ -77,13 +129,46 @@ export class NoiseSecureMessage extends DecodedMessage {}
* codec will be encrypted with the cipherstates and message nametags that were * codec will be encrypted with the cipherstates and message nametags that were
* created after a handshake is complete * created after a handshake is complete
*/ */
export class NoiseSecureTransferEncoder extends Encoder { export class NoiseSecureTransferEncoder implements IEncoder {
/** /**
* @param contentTopic content topic on which the encoded WakuMessages were sent * @param contentTopic content topic on which the encoded WakuMessages were sent
* @param hsResult handshake result obtained after the handshake is successful * @param hsResult handshake result obtained after the handshake is successful
*/ */
constructor(public contentTopic: string, private hsResult: HandshakeResult) { constructor(public contentTopic: string, private hsResult: HandshakeResult, public ephemeral: boolean = true) {}
super(contentTopic);
toWire(message: IMessage): Promise<Uint8Array | undefined> {
return this.encode(message);
}
toProtoObj(message: IMessage): Promise<IProtoMessage | undefined> {
return this.encodeProto(message);
}
async encode(message: IMessage): Promise<Uint8Array | undefined> {
const protoMessage = await this.encodeProto(message);
if (!protoMessage) return;
return WakuMessage.encode(protoMessage);
}
async encodeProto(message: IMessage): Promise<IProtoMessage | undefined> {
const timestamp = message.timestamp ?? new Date();
if (!message.payload) {
log("No payload to encrypt, skipping: ", message);
return;
}
const preparedPayload = this.hsResult.writeMessage(message.payload);
const payload = preparedPayload.serialize();
return {
payload,
rateLimitProof: undefined,
ephemeral: this.ephemeral,
version: version,
contentTopic: this.contentTopic,
timestamp: BigInt(timestamp.valueOf()) * OneMillion,
};
} }
} }
@ -93,35 +178,44 @@ export class NoiseSecureTransferEncoder extends Encoder {
* messages with the cipherstates and message nametags that were created after a * messages with the cipherstates and message nametags that were created after a
* handshake is complete * handshake is complete
*/ */
export class NoiseSecureTransferDecoder extends Decoder { export class NoiseSecureTransferDecoder implements IDecoder<NoiseSecureMessage> {
/** /**
* @param contentTopic content topic on which the encoded WakuMessages were sent * @param contentTopic content topic on which the encoded WakuMessages were sent
* @param hsResult handshake result obtained after the handshake is successful * @param hsResult handshake result obtained after the handshake is successful
*/ */
constructor(public contentTopic: string, private hsResult: HandshakeResult) { constructor(public contentTopic: string, private hsResult: HandshakeResult) {}
super(contentTopic);
fromProtoObj(proto: IProtoMessage): Promise<NoiseSecureMessage | undefined> {
return this.decode(proto);
} }
async fromProtoObj(proto: proto.WakuMessage): Promise<NoiseSecureMessage | undefined> { fromWireToProtoObj(bytes: Uint8Array): Promise<IProtoMessage | undefined> {
return this.decodeProto(bytes);
}
decodeProto(bytes: Uint8Array): Promise<IProtoMessage | undefined> {
const protoMessage = WakuMessage.decode(bytes);
log("Message decoded", protoMessage);
return Promise.resolve(protoMessage as IProtoMessage);
}
async decode(proto: IProtoMessage): Promise<NoiseSecureMessage | undefined> {
// https://github.com/status-im/js-waku/issues/921 // https://github.com/status-im/js-waku/issues/921
if (proto.version === undefined) { if (proto.version === undefined) {
proto.version = 0; proto.version = 0;
} }
if (proto.version !== version) { if (proto.version !== version) {
log("Failed to decode due to incorrect version, expected:", version, ", actual:", proto.version); log("Failed to decode due to incorrect version, expected:", version, ", actual:", proto.version);
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
if (!proto.payload) { if (!proto.payload) {
log("No payload, skipping: ", proto); log("No payload, skipping: ", proto);
return; return;
} }
try { try {
const payloadV2 = PayloadV2.deserialize(proto.payload); const payloadV2 = PayloadV2.deserialize(proto.payload);
const decryptedPayload = this.hsResult.readMessage(payloadV2); const decryptedPayload = this.hsResult.readMessage(payloadV2);
return new NoiseSecureMessage(proto); return new NoiseSecureMessage(proto, decryptedPayload);
} catch (err) { } catch (err) {
log("could not decode message ", err); log("could not decode message ", err);
return; return;