diff options
author | j-berman <justinberman@protonmail.com> | 2021-11-15 05:23:53 -0800 |
---|---|---|
committer | j-berman <justinberman@protonmail.com> | 2022-04-18 00:49:53 -0700 |
commit | ea87b30f8907ee11252433811e7a7d0c46758cca (patch) | |
tree | 61dedf56a781a83285be092b078019bebdc94f2e /src/crypto/crypto.cpp | |
parent | Merge pull request #8207 (diff) | |
download | monero-ea87b30f8907ee11252433811e7a7d0c46758cca.tar.xz |
Add view tags to outputs to reduce wallet scanning time
Implements view tags as proposed by @UkoeHB in MRL issue
https://github.com/monero-project/research-lab/issues/73
At tx construction, the sender adds a 1-byte view tag to each
output. The view tag is derived from the sender-receiver
shared secret. When scanning for outputs, the receiver can
check the view tag for a match, in order to reduce scanning
time. When the view tag does not match, the wallet avoids the
more expensive EC operations when deriving the output public
key using the shared secret.
Diffstat (limited to 'src/crypto/crypto.cpp')
-rw-r--r-- | src/crypto/crypto.cpp | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 1f46164d7..77a36069a 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -749,4 +749,28 @@ POP_WARNINGS sc_sub(&h, &h, &sum); return sc_isnonzero(&h) == 0; } + + void crypto_ops::derive_view_tag(const key_derivation &derivation, size_t output_index, view_tag &view_tag) { + #pragma pack(push, 1) + struct { + char salt[8]; // view tag domain-separator + key_derivation derivation; + char output_index[(sizeof(size_t) * 8 + 6) / 7]; + } buf; + #pragma pack(pop) + + char *end = buf.output_index; + memcpy(buf.salt, "view_tag", 8); // leave off null terminator + buf.derivation = derivation; + tools::write_varint(end, output_index); + assert(end <= buf.output_index + sizeof buf.output_index); + + // view_tag_full = H[salt|derivation|output_index] + hash view_tag_full; + cn_fast_hash(&buf, end - reinterpret_cast<char *>(&buf), view_tag_full); + + // only need a slice of view_tag_full to realize optimal perf/space efficiency + static_assert(sizeof(crypto::view_tag) <= sizeof(view_tag_full), "view tag should not be larger than hash result"); + memcpy(&view_tag, &view_tag_full, sizeof(crypto::view_tag)); + } } |