Danish Arora fea4f2577b
chore(message-hash): use timestamp in nanoseconds instead of milliseconds (#2094)
* chore: convert timestamp from miliseconds to nanoseconds

* chore: test against hash accounting for nanoseconds instead of milliseconds
the hash used was calculated using timestamp in milliseconds, instead of nanoseconds (not part of the RFC test vectors)Y
2024-08-01 15:19:35 +05:30

62 lines
1.4 KiB
TypeScript

import { sha256 } from "@noble/hashes/sha256";
import type { IDecodedMessage, IProtoMessage } from "@waku/interfaces";
import { isDefined } from "@waku/utils";
import {
bytesToUtf8,
concat,
numberToBytes,
utf8ToBytes
} from "@waku/utils/bytes";
/**
* Deterministic Message Hashing as defined in
* [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14/#deterministic-message-hashing)
*/
export function messageHash(
pubsubTopic: string,
message: IProtoMessage | IDecodedMessage
): Uint8Array {
const pubsubTopicBytes = utf8ToBytes(pubsubTopic);
const contentTopicBytes = utf8ToBytes(message.contentTopic);
const timestampBytes = tryConvertTimestampToBytes(message.timestamp);
const bytes = concat(
[
pubsubTopicBytes,
message.payload,
contentTopicBytes,
message.meta,
timestampBytes
].filter(isDefined)
);
return sha256(bytes);
}
function tryConvertTimestampToBytes(
timestamp: Date | number | bigint | undefined
): undefined | Uint8Array {
if (!timestamp) {
return;
}
let bigIntTimestamp: bigint;
if (typeof timestamp === "bigint") {
bigIntTimestamp = timestamp;
} else {
bigIntTimestamp = BigInt(timestamp.valueOf()) * 1000000n;
}
return numberToBytes(bigIntTimestamp);
}
export function messageHashStr(
pubsubTopic: string,
message: IProtoMessage | IDecodedMessage
): string {
const hash = messageHash(pubsubTopic, message);
const hashStr = bytesToUtf8(hash);
return hashStr;
}