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.
This commit is contained in:
j-berman 2021-11-15 05:23:53 -08:00
parent 6694597974
commit ea87b30f89
39 changed files with 1165 additions and 230 deletions

View file

@ -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));
}
}