From a57bea299bdf71cdfb19dd6bd4b1f1c615fe1974 Mon Sep 17 00:00:00 2001 From: Lorenzo Delgado Date: Thu, 2 Mar 2023 11:41:41 +0100 Subject: [PATCH] feat(message): added waku message deterministic hashing --- tests/all_tests_v2.nim | 4 ++ tests/v2/test_waku_message_digest.nim | 85 ++++++++++++++++++++++++ tests/v2/testlib/waku2.nim | 2 + waku/v2/protocol/waku_message.nim | 6 +- waku/v2/protocol/waku_message/digest.nim | 38 +++++++++++ 5 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 tests/v2/test_waku_message_digest.nim create mode 100644 waku/v2/protocol/waku_message/digest.nim diff --git a/tests/all_tests_v2.nim b/tests/all_tests_v2.nim index 571849668..443d503d9 100644 --- a/tests/all_tests_v2.nim +++ b/tests/all_tests_v2.nim @@ -6,6 +6,10 @@ import ./all_tests_common ## Waku v2 +# Waku message test suite +import + ./v2/test_waku_message_digest + # Waku archive test suite import ./v2/waku_archive/test_driver_queue_index, diff --git a/tests/v2/test_waku_message_digest.nim b/tests/v2/test_waku_message_digest.nim new file mode 100644 index 000000000..055b82ae0 --- /dev/null +++ b/tests/v2/test_waku_message_digest.nim @@ -0,0 +1,85 @@ +{.used.} + +import + stew/byteutils, + testutils/unittests +import + ../../waku/v2/protocol/waku_message/digest, + ./testlib/waku2 + +suite "Waku Message - Deterministic hashing": + + test "digest computation - empty meta field": + ## Test vector: + ## + ## pubsub_topic = 0x2f77616b752f322f64656661756c742d77616b752f70726f746f + ## waku_message.payload = 0x010203045445535405060708 + ## waku_message.content_topic = 0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f + ## waku_message.meta = + ## + ## message_hash = 0x87619d05e563521d9126749b45bd4cc2430df0607e77e23572d874ed9c1aaa62 + + ## Given + let pubsubTopic = DefaultPubsubTopic # /waku/2/default-waku/proto + let message = fakeWakuMessage( + contentTopic = DefaultContentTopic, # /waku/2/default-content/proto + payload = "\x01\x02\x03\x04TEST\x05\x06\x07\x08".toBytes(), + meta = newSeq[byte]() + ) + + ## When + let messageHash = digest(pubsubTopic, message) + + ## Then + check: + messageHash.toHex() == "87619d05e563521d9126749b45bd4cc2430df0607e77e23572d874ed9c1aaa62" + + test "digest computation - meta field (12 bytes)": + ## Test vector: + ## + ## pubsub_topic = 0x2f77616b752f322f64656661756c742d77616b752f70726f746f + ## waku_message.payload = 0x010203045445535405060708 + ## waku_message.content_topic = 0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f + ## waku_message.meta = 0x73757065722d736563726574 + ## + ## message_hash = 0x4fdde1099c9f77f6dae8147b6b3179aba1fc8e14a7bf35203fc253ee479f135f + + ## Given + let pubsubTopic = DefaultPubsubTopic # /waku/2/default-waku/proto + let message = fakeWakuMessage( + contentTopic = DefaultContentTopic, # /waku/2/default-content/proto + payload = "\x01\x02\x03\x04TEST\x05\x06\x07\x08".toBytes(), + meta = "\x73\x75\x70\x65\x72\x2d\x73\x65\x63\x72\x65\x74".toBytes() + ) + + ## When + let messageHash = digest(pubsubTopic, message) + + ## Then + check: + messageHash.toHex() == "4fdde1099c9f77f6dae8147b6b3179aba1fc8e14a7bf35203fc253ee479f135f" + + test "digest computation - zero length payload": + ## Test vector: + ## + ## pubsub_topic = 0x2f77616b752f322f64656661756c742d77616b752f70726f746f + ## waku_message.payload = [] + ## waku_message.content_topic = 0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f + ## waku_message.meta = 0x73757065722d736563726574 + ## + ## message_hash = 0xe1a9596237dbe2cc8aaf4b838c46a7052df6bc0d42ba214b998a8bfdbe8487d6 + + ## Given + let pubsubTopic = DefaultPubsubTopic # /waku/2/default-waku/proto + let message = fakeWakuMessage( + contentTopic = DefaultContentTopic, # /waku/2/default-content/proto + payload = newSeq[byte](), + meta = "\x73\x75\x70\x65\x72\x2d\x73\x65\x63\x72\x65\x74".toBytes() + ) + + ## When + let messageHash = digest(pubsubTopic, message) + + ## Then + check: + messageHash.toHex() == "e1a9596237dbe2cc8aaf4b838c46a7052df6bc0d42ba214b998a8bfdbe8487d6" diff --git a/tests/v2/testlib/waku2.nim b/tests/v2/testlib/waku2.nim index b7987aca9..c439bd827 100644 --- a/tests/v2/testlib/waku2.nim +++ b/tests/v2/testlib/waku2.nim @@ -38,6 +38,7 @@ export proc fakeWakuMessage*( payload: string|seq[byte] = "TEST-PAYLOAD", contentTopic = DefaultContentTopic, + meta = newSeq[byte](), ts = now(), ephemeral = false ): WakuMessage = @@ -50,6 +51,7 @@ proc fakeWakuMessage*( WakuMessage( payload: payloadBytes, contentTopic: contentTopic, + meta: meta, version: 2, timestamp: ts, ephemeral: ephemeral diff --git a/waku/v2/protocol/waku_message.nim b/waku/v2/protocol/waku_message.nim index c6396f10a..2a3d85a3e 100644 --- a/waku/v2/protocol/waku_message.nim +++ b/waku/v2/protocol/waku_message.nim @@ -1,7 +1,9 @@ import ./waku_message/message, - ./waku_message/codec + ./waku_message/codec, + ./waku_message/digest export message, - codec + codec, + digest diff --git a/waku/v2/protocol/waku_message/digest.nim b/waku/v2/protocol/waku_message/digest.nim new file mode 100644 index 000000000..672c5e529 --- /dev/null +++ b/waku/v2/protocol/waku_message/digest.nim @@ -0,0 +1,38 @@ +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + + +import + std/sequtils, + stew/byteutils, + nimcrypto/sha2 +import + ./message + + +## 14/WAKU2-MESSAGE: Deterministic message hashing +## https://rfc.vac.dev/spec/14/#deterministic-message-hashing + +type WakuMessageDigest* = array[32, byte] + + +converter toBytesArray*(digest: MDigest[256]): WakuMessageDigest = + digest.data + +converter toBytes*(digest: MDigest[256]): seq[byte] = + toSeq(digest.data) + + +proc digest*(pubsubTopic: PubsubTopic, msg: WakuMessage): WakuMessageDigest = + var ctx: sha256 + ctx.init() + defer: ctx.clear() + + ctx.update(pubsubTopic.toBytes()) + ctx.update(msg.payload) + ctx.update(msg.contentTopic.toBytes()) + ctx.update(msg.meta) + + return ctx.finish() # Computes the hash