diff --git a/src/seraphis_core/jamtis_account_secrets.h b/src/seraphis_core/jamtis_account_secrets.h index 8c64b8eccdb..326dec3c7cb 100644 --- a/src/seraphis_core/jamtis_account_secrets.h +++ b/src/seraphis_core/jamtis_account_secrets.h @@ -84,7 +84,7 @@ void make_jamtis_generateimage_key(const crypto::secret_key &s_view_balance, * param: s_view_balance - s_vb * outparam: d_unlock_received_out - d_ur */ -void make_jamtis_unlockreceived_key(const crypto::secret_key &k_view_balance, +void make_jamtis_unlockreceived_key(const crypto::secret_key &s_view_balance, crypto::x25519_secret_key &d_view_received_out); /** * brief make_jamtis_exchangebase_pubkey - D_base @@ -100,7 +100,7 @@ void make_jamtis_exchangebase_pubkey(const crypto::x25519_secret_key &d_unlock_r * param: s_view_balance - s_vb * outparam: d_identify_received_out - d_ir */ -void make_jamtis_identifyreceived_key(const crypto::secret_key &k_view_balance, +void make_jamtis_identifyreceived_key(const crypto::secret_key &s_view_balance, crypto::x25519_secret_key &d_identify_received_out); /** * brief: make_jamtis_identifyreceived_pubkey - D_ir @@ -148,7 +148,7 @@ void make_jamtis_ciphertag_secret(const crypto::secret_key &s_generate_address, crypto::secret_key &s_cipher_tag_out); /** * brief: make_rct_spendkey - base public spendkey for RingCTv2 - * K_s = k_gi U + k_ps G + * K_s = k_gi G + k_ps U * param: k_generate_image - k_gi * param: k_prove_spend - k_ps * outparam: spend_pubkey_out - K_s diff --git a/src/seraphis_core/jamtis_address_utils.cpp b/src/seraphis_core/jamtis_address_utils.cpp index 79ea5143645..166bded1c0e 100644 --- a/src/seraphis_core/jamtis_address_utils.cpp +++ b/src/seraphis_core/jamtis_address_utils.cpp @@ -35,6 +35,7 @@ #include "cryptonote_config.h" #include "jamtis_account_secrets.h" #include "jamtis_support_types.h" +#include "misc_log_ex.h" #include "ringct/rctOps.h" #include "seraphis_crypto/sp_crypto_utils.h" #include "seraphis_crypto/sp_hash_functions.h" @@ -152,7 +153,7 @@ void make_jamtis_address_privkey(const rct::key &spend_pubkey, sp_hash_to_x25519_scalar(transcript.data(), transcript.size(), address_privkey_out.data); } //------------------------------------------------------------------------------------------------------------------- -void make_jamtis_address_spend_key(const rct::key &spend_pubkey, +void make_jamtis_address_spend_key_sp(const rct::key &spend_pubkey, const crypto::secret_key &s_generate_address, const address_index_t &j, rct::key &address_spendkey_out) @@ -171,6 +172,41 @@ void make_jamtis_address_spend_key(const rct::key &spend_pubkey, mask_key(address_extension_key_g, address_spendkey_out, address_spendkey_out); //k^j_g G + k^j_x X + k^j_u U + K_s } //------------------------------------------------------------------------------------------------------------------- +void make_jamtis_address_spend_key_rct(const rct::key &spend_pubkey, + const crypto::secret_key &s_generate_address, + const address_index_t &j, + rct::key &address_spendkey_out) +{ + // K^j_s = k^j_g G + k^j_u U + K_s + crypto::secret_key address_extension_key_u; + crypto::secret_key address_extension_key_g; + make_jamtis_spendkey_extension_u(spend_pubkey, s_generate_address, j, address_extension_key_u); //k^j_u + make_jamtis_spendkey_extension_g(spend_pubkey, s_generate_address, j, address_extension_key_g); //k^j_g + + address_spendkey_out = spend_pubkey; //K_s + extend_seraphis_spendkey_u(address_extension_key_u, address_spendkey_out); //k^j_u U + K_s + mask_key(address_extension_key_g, address_spendkey_out, address_spendkey_out); //k^j_g G + k^j_u U + K_s +} +//------------------------------------------------------------------------------------------------------------------- +void make_jamtis_address_spend_key(const JamtisOnetimeAddressFormat onetime_address_format, + const rct::key &spend_pubkey, + const crypto::secret_key &s_generate_address, + const address_index_t &j, + rct::key &address_spendkey_out) +{ + switch (onetime_address_format) + { + case JamtisOnetimeAddressFormat::RINGCT_V2: + make_jamtis_address_spend_key_rct(spend_pubkey, s_generate_address, j, address_spendkey_out); + break; + case JamtisOnetimeAddressFormat::SERAPHIS: + make_jamtis_address_spend_key_sp(spend_pubkey, s_generate_address, j, address_spendkey_out); + break; + default: + ASSERT_MES_AND_THROW("make jamtis address spend key: unrecognized onetime address format"); + } +} +//------------------------------------------------------------------------------------------------------------------- void make_seraphis_key_image_jamtis_style(const rct::key &spend_pubkey, const crypto::secret_key &k_view_balance, const crypto::secret_key &spendkey_extension_x, diff --git a/src/seraphis_core/jamtis_address_utils.h b/src/seraphis_core/jamtis_address_utils.h index c20ff133540..982b55e3907 100644 --- a/src/seraphis_core/jamtis_address_utils.h +++ b/src/seraphis_core/jamtis_address_utils.h @@ -128,12 +128,37 @@ void make_jamtis_address_privkey(const rct::key &spend_pubkey, /** * brief: make_jamtis_address_spend_key - K^j_s * - K^j_s = k^j_g G + k^j_x X + k^j_u U + K_s -* param: spend_pubkey - K_s = k_vb X + k_m U +* param: spend_pubkey - K_s = k_gi X + k_ps U +* param: s_generate_address - s_ga +* param: j - address index +* outparam: address_spendkey_out - K^j_s +*/ +void make_jamtis_address_spend_key_sp(const rct::key &spend_pubkey, + const crypto::secret_key &s_generate_address, + const address_index_t &j, + rct::key &address_spendkey_out); +/** +* brief: make_jamtis_address_spend_key - K^j_s +* - K^j_s = k^j_g G + k^j_u U + K_s +* param: spend_pubkey - K_s = k_gi G + k_ps U * param: s_generate_address - s_ga * param: j - address index * outparam: address_spendkey_out - K^j_s */ -void make_jamtis_address_spend_key(const rct::key &spend_pubkey, +void make_jamtis_address_spend_key_rct(const rct::key &spend_pubkey, + const crypto::secret_key &s_generate_address, + const address_index_t &j, + rct::key &address_spendkey_out); +/** +* brief: make_jamtis_address_spend_key - K^j_s +* - K^j_s = ... + K_s +* param: spend_pubkey - K_s +* param: s_generate_address - s_ga +* param: j - address index +* outparam: address_spendkey_out - K^j_s +*/ +void make_jamtis_address_spend_key(const JamtisOnetimeAddressFormat onetime_address_format, + const rct::key &spend_pubkey, const crypto::secret_key &s_generate_address, const address_index_t &j, rct::key &address_spendkey_out); diff --git a/src/seraphis_core/jamtis_destination.cpp b/src/seraphis_core/jamtis_destination.cpp index 2441b616969..d2869748fd1 100644 --- a/src/seraphis_core/jamtis_destination.cpp +++ b/src/seraphis_core/jamtis_destination.cpp @@ -61,7 +61,7 @@ bool operator==(const JamtisDestinationV1 &a, const JamtisDestinationV1 &b) (a.addr_tag == b.addr_tag); } //------------------------------------------------------------------------------------------------------------------- -void make_jamtis_destination_v1(const rct::key &spend_pubkey, +void make_jamtis_destination_v1_sp(const rct::key &spend_pubkey, const crypto::x25519_pubkey &filterassist_pubkey, const crypto::x25519_pubkey &identifyreceived_pubkey, const crypto::x25519_pubkey &exchangebase_pubkey, @@ -69,8 +69,45 @@ void make_jamtis_destination_v1(const rct::key &spend_pubkey, const address_index_t &j, JamtisDestinationV1 &destination_out) { - // K^j_s = k^j_g G + k^j_x X + k^j_u U + K_s - make_jamtis_address_spend_key(spend_pubkey, s_generate_address, j, destination_out.addr_Ks); + make_jamtis_destination_v1(JamtisOnetimeAddressFormat::SERAPHIS, + spend_pubkey, + filterassist_pubkey, + identifyreceived_pubkey, + exchangebase_pubkey, + s_generate_address, + j, + destination_out); +} +//------------------------------------------------------------------------------------------------------------------- +void make_jamtis_destination_v1_rct(const rct::key &spend_pubkey, + const crypto::x25519_pubkey &filterassist_pubkey, + const crypto::x25519_pubkey &identifyreceived_pubkey, + const crypto::x25519_pubkey &exchangebase_pubkey, + const crypto::secret_key &s_generate_address, + const address_index_t &j, + JamtisDestinationV1 &destination_out) +{ + make_jamtis_destination_v1(JamtisOnetimeAddressFormat::RINGCT_V2, + spend_pubkey, + filterassist_pubkey, + identifyreceived_pubkey, + exchangebase_pubkey, + s_generate_address, + j, + destination_out); +} +//------------------------------------------------------------------------------------------------------------------- +void make_jamtis_destination_v1(const JamtisOnetimeAddressFormat onetime_address_format, + const rct::key &spend_pubkey, + const crypto::x25519_pubkey &filterassist_pubkey, + const crypto::x25519_pubkey &identifyreceived_pubkey, + const crypto::x25519_pubkey &exchangebase_pubkey, + const crypto::secret_key &s_generate_address, + const address_index_t &j, + JamtisDestinationV1 &destination_out) +{ + // K^j_s = ... + K_s + make_jamtis_address_spend_key(onetime_address_format, spend_pubkey, s_generate_address, j, destination_out.addr_Ks); // d^j_a = H_n_x25519(K_s, j, s^j_gen) crypto::x25519_secret_key address_privkey; @@ -93,7 +130,8 @@ void make_jamtis_destination_v1(const rct::key &spend_pubkey, destination_out.addr_tag = cipher_address_index(ciphertag_secret, j); } //------------------------------------------------------------------------------------------------------------------- -bool try_get_jamtis_index_from_destination_v1(const JamtisDestinationV1 &destination, +bool try_get_jamtis_index_from_destination_v1(const JamtisOnetimeAddressFormat onetime_address_format, + const JamtisDestinationV1 &destination, const rct::key &spend_pubkey, const crypto::x25519_pubkey &filterassist_pubkey, const crypto::x25519_pubkey &identifyreceived_pubkey, @@ -112,7 +150,8 @@ bool try_get_jamtis_index_from_destination_v1(const JamtisDestinationV1 &destina // recreate the destination JamtisDestinationV1 test_destination; - make_jamtis_destination_v1(spend_pubkey, + make_jamtis_destination_v1(onetime_address_format, + spend_pubkey, filterassist_pubkey, identifyreceived_pubkey, exchangebase_pubkey, diff --git a/src/seraphis_core/jamtis_destination.h b/src/seraphis_core/jamtis_destination.h index a4ed45c24c4..14dffee5111 100644 --- a/src/seraphis_core/jamtis_destination.h +++ b/src/seraphis_core/jamtis_destination.h @@ -88,7 +88,7 @@ void make_jamtis_destination_v1_sp(const rct::key &spend_pubkey, JamtisDestinationV1 &destination_out); /** * brief: make_jamtis_destination_v1 - make a destination address for the RingCTv2 protocol -* param: spend_pubkey - K_s = k_gi U + k_ps G +* param: spend_pubkey - K_s = k_gi G + k_ps U * param: filterassist_pubkey - D_fa = d_fa D_base * param: identifyreceived_pubkey - D_ir = d_ir D_base * param: exchangebase_pubkey - D_base = d_ur xG @@ -104,6 +104,24 @@ void make_jamtis_destination_v1_rct(const rct::key &spend_pubkey, const address_index_t &j, JamtisDestinationV1 &destination_out); /** +* brief: make_jamtis_destination_v1 - make a destination address for the RingCTv2 protocol +* param: spend_pubkey - K_s = [ringct: k_gi G + k_ps U] = [seraphis: k_gi X + k_ps U] +* param: filterassist_pubkey - D_fa = d_fa D_base +* param: identifyreceived_pubkey - D_ir = d_ir D_base +* param: exchangebase_pubkey - D_base = d_ur xG +* param: s_generate_address - s_ga +* param: j - address_index +* outparam: destination_out - the full address, with address tag +*/ +void make_jamtis_destination_v1(const JamtisOnetimeAddressFormat onetime_address_format, + const rct::key &spend_pubkey, + const crypto::x25519_pubkey &filterassist_pubkey, + const crypto::x25519_pubkey &identifyreceived_pubkey, + const crypto::x25519_pubkey &exchangebase_pubkey, + const crypto::secret_key &s_generate_address, + const address_index_t &j, + JamtisDestinationV1 &destination_out); +/** * brief: try_get_jamtis_index_from_destination_v1 - check if a destination can be recreated, then return its address index * - note: partial-recreation of a destination will return FALSE * param: destination - destination address to recreate @@ -115,7 +133,8 @@ void make_jamtis_destination_v1_rct(const rct::key &spend_pubkey, * outparam: j_out - address index (if successful) * return: true if the destination can be recreated */ -bool try_get_jamtis_index_from_destination_v1(const JamtisDestinationV1 &destination, +bool try_get_jamtis_index_from_destination_v1(const JamtisOnetimeAddressFormat onetime_address_format, + const JamtisDestinationV1 &destination, const rct::key &spend_pubkey, const crypto::x25519_pubkey &filterassist_pubkey, const crypto::x25519_pubkey &identifyreceived_pubkey, diff --git a/src/seraphis_core/jamtis_enote_utils.cpp b/src/seraphis_core/jamtis_enote_utils.cpp index ac13f2c2fcb..47ba2f79b75 100644 --- a/src/seraphis_core/jamtis_enote_utils.cpp +++ b/src/seraphis_core/jamtis_enote_utils.cpp @@ -225,14 +225,11 @@ void make_jamtis_view_tag(const secret256_ptr_t x_fa, view_tag_t naked_secondary_view_tag; make_jamtis_naked_secondary_view_tag(x_ir, onetime_address, naked_secondary_view_tag); - const std::uint32_t primary_mask = (1 << num_primary_view_tag_bits) - 1; - const std::uint32_t comp_mask = ~primary_mask; + const std::uint32_t primary_mask{(static_cast(1) << num_primary_view_tag_bits) - 1}; // view_tag = naked_primary_view_tag[:npbits] || naked_secondary_view_tag[:ncbits] - std::uint32_t combined_view_tag_u32 = (vttou32(naked_primary_view_tag) & primary_mask) | - ((vttou32(naked_secondary_view_tag) << num_primary_view_tag_bits) & comp_mask); - - combined_view_tag_u32 = SWAP32LE(combined_view_tag_u32); + const std::uint32_t combined_view_tag_u32{SWAP32LE((vttou32(naked_primary_view_tag) & primary_mask) | + (vttou32(naked_secondary_view_tag) & ~primary_mask))}; memcpy(view_tag_out.bytes, &combined_view_tag_u32, VIEW_TAG_BYTES); } //------------------------------------------------------------------------------------------------------------------- @@ -512,9 +509,8 @@ bool test_jamtis_primary_view_tag(const secret256_ptr_t x_fa, naked_primary_view_tag); // primary_view_tag' ?= primary_view_tag - const std::uint32_t partial_recomputed_view_tag = vttou32(naked_primary_view_tag); - const std::uint32_t primary_mask = (1 << num_primary_view_tag_bits) - 1; - return 0 == ((partial_recomputed_view_tag ^ vttou32(view_tag)) & primary_mask); + const std::uint32_t primary_mask = (static_cast(1) << num_primary_view_tag_bits) - 1; + return 0 == ((vttou32(naked_primary_view_tag) ^ vttou32(view_tag)) & primary_mask); } //------------------------------------------------------------------------------------------------------------------- bool test_jamtis_primary_view_tag(const crypto::x25519_secret_key &d_filter_assist, @@ -536,7 +532,8 @@ bool test_jamtis_primary_view_tag(const crypto::x25519_secret_key &d_filter_assi bool test_jamtis_secondary_view_tag(const secret256_ptr_t x_ir, const rct::key &onetime_address, const view_tag_t view_tag, - const std::uint8_t num_primary_view_tag_bits) + const std::uint8_t num_primary_view_tag_bits, + bool &matched_all_secondary_bits_out) { // npbits can't be greater than total tag size (duh) CHECK_AND_ASSERT_THROW_MES(num_primary_view_tag_bits <= 8 * VIEW_TAG_BYTES, @@ -547,10 +544,10 @@ bool test_jamtis_secondary_view_tag(const secret256_ptr_t x_ir, make_jamtis_naked_secondary_view_tag(x_ir, onetime_address, naked_secondary_view_tag); // secondary_view_tag' ?= secondary_view_tag - const std::uint32_t ncbits = 8 * VIEW_TAG_BYTES - num_primary_view_tag_bits; - const std::uint32_t secondary_mask = ((1ul << ncbits) - 1) << num_primary_view_tag_bits; - const std::uint32_t partial_recomputed_view_tag = vttou32(naked_secondary_view_tag) << num_primary_view_tag_bits; - return 0 == ((partial_recomputed_view_tag ^ vttou32(view_tag)) & secondary_mask); + const std::uint32_t secondary_mask{~((static_cast(1) << num_primary_view_tag_bits) - 1)}; + + matched_all_secondary_bits_out = naked_secondary_view_tag == view_tag; + return 0 == ((vttou32(naked_secondary_view_tag) ^ vttou32(view_tag)) & secondary_mask); } //------------------------------------------------------------------------------------------------------------------- bool try_get_jamtis_amount(const rct::key &sender_receiver_secret, diff --git a/src/seraphis_core/jamtis_enote_utils.h b/src/seraphis_core/jamtis_enote_utils.h index ba1a9a01b99..86f6618e452 100644 --- a/src/seraphis_core/jamtis_enote_utils.h +++ b/src/seraphis_core/jamtis_enote_utils.h @@ -348,12 +348,14 @@ bool test_jamtis_primary_view_tag(const crypto::x25519_secret_key &d_filter_assi * param: onetime_address - Ko * param: view_tag - view_tag * param: num_primary_view_tag_bits - npbits +* outparam: matched_all_secondary_bits_out - true if all secondary view tag bits match for the entire view tag * return: true if successfully recomputed the secondary view tag */ bool test_jamtis_secondary_view_tag(const secret256_ptr_t x_ir, const rct::key &onetime_address, const view_tag_t view_tag, - const std::uint8_t num_primary_view_tag_bits); + const std::uint8_t num_primary_view_tag_bits, + bool &matched_all_secondary_bits_out); /** * brief: try_get_jamtis_amount - test recreating the amount commitment; if it is recreate-able, return the amount * param: sender_receiver_secret - q diff --git a/src/seraphis_core/jamtis_support_types.h b/src/seraphis_core/jamtis_support_types.h index 3ea6f4dca7c..c07ecea832d 100644 --- a/src/seraphis_core/jamtis_support_types.h +++ b/src/seraphis_core/jamtis_support_types.h @@ -79,7 +79,8 @@ enum class JamtisEnoteType : unsigned char { SELF_SPEND = 0, CHANGE = 1, - PLAIN = 2 + PLAIN = 2, + MAX = PLAIN }; /// jamtis self-send types, used to define enote-construction procedure for self-sends diff --git a/src/seraphis_main/enote_record_types.h b/src/seraphis_main/enote_record_types.h index 64becc6dde1..4dc9ea6bf33 100644 --- a/src/seraphis_main/enote_record_types.h +++ b/src/seraphis_main/enote_record_types.h @@ -141,9 +141,9 @@ struct SpBasicEnoteRecordV1 final std::uint8_t num_primary_view_tag_bits; /// context of the tx input(s) associated with this enote rct::key input_context; - /// indicates if this enote passed the exclusive-enote view tag check - /// - If it did not pass, then it *might* be an auxiliary enote. - bool passed_exclusive_check; + /// indicates if this enote passed the primary view tag check + /// - If it did not pass, then we only have to check for a 'hidden' self-send enote. + bool primary_vt_matches; }; //// diff --git a/src/seraphis_main/enote_record_utils.cpp b/src/seraphis_main/enote_record_utils.cpp index 14247ec8c41..4db59fb2922 100644 --- a/src/seraphis_main/enote_record_utils.cpp +++ b/src/seraphis_main/enote_record_utils.cpp @@ -51,6 +51,7 @@ extern "C" //third party headers //standard headers +#include #undef MONERO_DEFAULT_LOG_CATEGORY @@ -60,37 +61,6 @@ namespace sp { //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- -namespace -{ -enum class BalanceRecoveryPath -{ - PLAIN, - EXCLUSIVE_SELFSEND, - AUXILIARY_SELFSEND -}; - -static constexpr jamtis::JamtisSelfSendType EXCLUSIVE_SELFSEND_TYPES[2] = { - jamtis::JamtisSelfSendType::EXCLUSIVE_SELF_SPEND, jamtis::JamtisSelfSendType::EXCLUSIVE_CHANGE}; -static constexpr jamtis::JamtisSelfSendType AUXILIARY_SELFSEND_TYPES[2] = { - jamtis::JamtisSelfSendType::AUXILIARY_SELF_SPEND, jamtis::JamtisSelfSendType::AUXILIARY_CHANGE}; -} // anonymous namespace -//------------------------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------------------------- -static bool try_get_selfsend_types_for_balance_recovery_path(const BalanceRecoveryPath path, - const jamtis::JamtisSelfSendType *&self_send_types, - std::size_t &num_self_send_types) -{ - switch (path) - { - case BalanceRecoveryPath::PLAIN: return false; - case BalanceRecoveryPath::EXCLUSIVE_SELFSEND: self_send_types = EXCLUSIVE_SELFSEND_TYPES; num_self_send_types = 2; return true; - case BalanceRecoveryPath::AUXILIARY_SELFSEND: self_send_types = AUXILIARY_SELFSEND_TYPES; num_self_send_types = 2; return true; - default: - throw std::logic_error("bug: unexpected BalanceRecoveryPath enum variant"); - } -} -//------------------------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------------------------- static void make_enote_view_extensions_helper(const rct::key &jamtis_spend_pubkey, const crypto::secret_key &s_generate_address, const jamtis::address_index_t &j, @@ -131,30 +101,64 @@ static void make_enote_view_extensions_helper(const rct::key &jamtis_spend_pubke //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- static void make_seraphis_key_image_helper(const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &k_generate_image, const crypto::secret_key &enote_view_extension_x, const crypto::secret_key &enote_view_extension_u, crypto::key_image &key_image_out) { - // make key image: (k_u + k_m)/(k_x + k_vb) U - rct::key spend_pubkey_U_component{jamtis_spend_pubkey}; //k_vb X + k_m U - reduce_seraphis_spendkey_x(k_view_balance, spend_pubkey_U_component); //k_m U + // make key image: (k_u + k_ps)/(k_x + k_gi) U + rct::key spend_pubkey_U_component{jamtis_spend_pubkey}; //k_gi X + k_ps U + reduce_seraphis_spendkey_x(k_generate_image, spend_pubkey_U_component); //k_ps U extend_seraphis_spendkey_u(enote_view_extension_u, spend_pubkey_U_component); //(k_u + k_m) U - make_seraphis_key_image(add_secrets(enote_view_extension_x, k_view_balance), + make_seraphis_key_image(add_secrets(enote_view_extension_x, k_generate_image), rct::rct2pk(spend_pubkey_U_component), - key_image_out); //(k_u + k_m)/(k_x + k_vb) U + key_image_out); //(k_u + k_ps)/(k_x + k_gi) U } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- +struct lazy_scmul_key +{ + const crypto::x25519_scalar &privkey; + const crypto::x25519_pubkey &pubkey; + crypto::x25519_pubkey dhe; + bool done{false}; + jamtis::secret256_ptr_t operator()() + { + if (!done) + { + crypto::x25519_scmul_key(privkey, pubkey, dhe); + done = true; + } + return dhe.data; + } +}; +//------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------- +struct lazy_make_x_ur_plain +{ + const rct::key &jamtis_spend_pubkey; + const crypto::secret_key &s_generate_address; + const jamtis::address_index_t &j; + const crypto::x25519_scalar &d_unlock_received; + const crypto::x25519_pubkey &enote_ephemeral_pubkey; + crypto::x25519_pubkey x_ur; + bool done{false}; + jamtis::secret256_ptr_t operator()() + { + if (!done) + { + crypto::x25519_secret_key address_privkey; + jamtis::make_jamtis_address_privkey(jamtis_spend_pubkey, s_generate_address, j, address_privkey); + crypto::x25519_invmul_key({d_unlock_received, address_privkey}, enote_ephemeral_pubkey, x_ur); + done = true; + } + return x_ur.data; + } +}; +//------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------- static bool try_recover_amount_commitment_info(const SpEnoteVariant &enote, - const crypto::x25519_pubkey &enote_ephemeral_pubkey, const rct::key &sender_receiver_secret, - const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, - const jamtis::address_index_t &address_index, - const crypto::secret_key &s_generate_address, - const BalanceRecoveryPath balance_recovery_path, rct::xmr_amount &amount_out, crypto::secret_key &amount_blinding_factor_out, jamtis::JamtisEnoteType &enote_type_out) @@ -170,164 +174,99 @@ static bool try_recover_amount_commitment_info(const SpEnoteVariant &enote, // otherwise we should have a normal enote const SpEnoteV1 *enote_ptr = enote.try_unwrap(); - CHECK_AND_ASSERT_THROW_MES(enote_ptr, "unknown enote type in try_get_amount_commitment_info"); + CHECK_AND_ASSERT_THROW_MES(enote_ptr, "unknown enote type in try_recover_amount_commitment_info"); - if (balance_recovery_path == BalanceRecoveryPath::PLAIN) + // for each enote type... + for (unsigned char i = 0; i <= static_cast(jamtis::JamtisEnoteType::MAX); ++i) { - enote_type_out = jamtis::JamtisEnoteType::PLAIN; - - // d^j_a = H_n_x25519(K_s, j, s^j_gen) - crypto::x25519_secret_key address_privkey; - jamtis::make_jamtis_address_privkey(jamtis_spend_pubkey, - s_generate_address, - address_index, - address_privkey); + enote_type_out = static_cast(i); - // baked_key = H_32(1/(d^j_a * d_vr) * D_e) - rct::key amount_baked_key; - jamtis::make_jamtis_amount_baked_key_plain_recipient(address_privkey, - d_view_received, - enote_ephemeral_pubkey, - amount_baked_key); - - return jamtis::try_get_jamtis_amount(sender_receiver_secret, - amount_baked_key, - enote_ptr->core.amount_commitment, - enote_ptr->encoded_amount, - amount_out, - amount_blinding_factor_out); - } - else // on self-send path - { - const jamtis::JamtisSelfSendType *self_send_types_to_check; - std::size_t num_self_send_types_to_check; - CHECK_AND_ASSERT_THROW_MES(try_get_selfsend_types_for_balance_recovery_path(balance_recovery_path, - self_send_types_to_check, - num_self_send_types_to_check), - "bug: no self send types provided for non-plain recovery path"); - - // for each applicable self send type... - for (std::size_t i = 0; i < num_self_send_types_to_check; ++i) - { - // baked_key = H_32[k_vb](q) - rct::key amount_baked_key; - jamtis::make_jamtis_amount_baked_key_selfsend(k_view_balance, - sender_receiver_secret, - self_send_types_to_check[i], - amount_baked_key); - - if (jamtis::try_get_jamtis_amount(sender_receiver_secret, - amount_baked_key, + // compute y' = H_32(q, enote_type) and a' = enc_amount XOR H_8(q, Ko) and check C ?= a' H + y' G + if (jamtis::try_get_jamtis_amount(sender_receiver_secret, + enote_ptr->core.onetime_address, + enote_type_out, enote_ptr->core.amount_commitment, - enote_ptr->encoded_amount, + enote_ptr->encrypted_amount, amount_out, amount_blinding_factor_out)) - { - // we successfully recovered enote amount, write the enote type and return, no more looping needed - CHECK_AND_ASSERT_THROW_MES(jamtis::try_get_jamtis_enote_type(self_send_types_to_check[i], - enote_type_out), "bug: could not convert self-send type into enote type"); - return true; - } - } - - return false; + return true; } + + return false; } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- -template +template static bool try_core_balance_recovery_v1(const SpEnoteVariant &enote, const crypto::x25519_pubkey &enote_ephemeral_pubkey, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, - const crypto::x25519_secret_key &d_filter_assist, + MakeXfa &&make_x_fa, // () -> jamtis::secret256_ptr_t functional object + const jamtis::secret256_ptr_t x_ir, + MakeXur &&make_x_ur, // (jamtis::address_index_t) -> jamtis::secret256_ptr_t functional object const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, - const BalanceRecoveryPath balance_recovery_path, rct::key &nominal_sender_receiver_secret_out, rct::key &recipient_address_spendkey_out, jamtis::JamtisEnoteType &enote_type_out, SpIntermediateLikeEnoteRecord &record_out) // type must contains a superset of SpIntermediateEnoteRecordV1's fields { - // "Core" balance recovery is the stages from nominal sender receiver secret derivation and + // "core" balance recovery is the stages from secondary view tag recomputation and // before key image calculation for both plain and self-send enotes. We attempt to recover the // following information and fill in the corresponding fields of an intermediate record: // whether enote is owned, address index, amount, amount blinding factor, enote type - // derive nominal sender-receiver secret q' for given path - if (balance_recovery_path == BalanceRecoveryPath::PLAIN) - { - // q' = H_32(xr * d_vr * xG, D_e, input_context) - jamtis::make_jamtis_sender_receiver_secret_plain(d_view_received, - enote_ephemeral_pubkey, - enote_ephemeral_pubkey, - input_context, - nominal_sender_receiver_secret_out); + // check secondary view tag + bool matched_all_secondary_bits; + if (!jamtis::test_jamtis_secondary_view_tag(x_ir, + onetime_address_ref(enote), + view_tag_ref(enote), + num_primary_view_tag_bits, + matched_all_secondary_bits)) + return false; + + // derive X_fa + const jamtis::secret256_ptr_t x_fa{make_x_fa()}; - // test complementary view tag - if (!jamtis::test_jamtis_complementary_view_tag(nominal_sender_receiver_secret_out, + // check primary view tag if not possibly a 'hidden' enote + if (!matched_all_secondary_bits) + if (!jamtis::test_jamtis_primary_view_tag(x_fa, + onetime_address_ref(enote), view_tag_ref(enote), num_primary_view_tag_bits)) return false; - } - else // send-send scan path - { - // q' = H_32[k_vb](D_e, input_context) - const bool is_auxiliary_self_send_type = balance_recovery_path == BalanceRecoveryPath::AUXILIARY_SELFSEND; - jamtis::make_jamtis_sender_receiver_secret_selfsend(k_view_balance, - enote_ephemeral_pubkey, - input_context, - is_auxiliary_self_send_type, - nominal_sender_receiver_secret_out); - } - // addr_tag' = addr_tag_enc XOR H_32(q, Ko) - const jamtis::address_tag_t addr_tag = jamtis::decrypt_address_tag( - nominal_sender_receiver_secret_out, onetime_address_ref(enote), addr_tag_enc_ref(enote)); + // addr_tag' = addr_tag_enc XOR H_32(x_fa, x_ir, Ko) + const jamtis::address_tag_t addr_tag = jamtis::decrypt_jamtis_address_tag(addr_tag_enc_ref(enote), x_fa, x_ir, + onetime_address_ref(enote)); // j' = decipher[s_ct](addr_tag') jamtis::decipher_address_index(cipher_context, addr_tag, record_out.address_index); // K^j_s' = k^j_g' G + k^j_x' X + k^j_u' U + K_s' - jamtis::make_jamtis_address_spend_key(jamtis_spend_pubkey, + jamtis::make_jamtis_address_spend_key_sp(jamtis_spend_pubkey, s_generate_address, record_out.address_index, recipient_address_spendkey_out); + + // derive X_ur + const jamtis::secret256_ptr_t x_ur{make_x_ur()}; + + // derive nominal sender-receiver secret q' = H_32(X_fa, X_ir, X_ur, D_e, input_context) + jamtis::make_jamtis_sender_receiver_secret(x_fa, x_ir, x_ur, enote_ephemeral_pubkey, input_context, + nominal_sender_receiver_secret_out); // [Ko' = k^o_g' G + k^o_x X' + k^o_u U' + K^j_s'] =?= Ko - if (!jamtis::test_jamtis_onetime_address(recipient_address_spendkey_out, + if (!jamtis::test_jamtis_onetime_address_sp(recipient_address_spendkey_out, nominal_sender_receiver_secret_out, amount_commitment_ref(enote), onetime_address_ref(enote))) return false; - // D^d_fa = d_fa D_e - crypto::x25519_pubkey dhe_fa; - crypto::x25519_scmul_key(d_filter_assist, enote_ephemeral_pubkey, dhe_fa); - - // if we use a standard view tag, check primary tag for correctness - if (balance_recovery_path != BalanceRecoveryPath::AUXILIARY_SELFSEND) - { - if (!jamtis::test_jamtis_primary_view_tag(dhe_fa, - onetime_address_ref(enote), - view_tag_ref(enote), - num_primary_view_tag_bits)) - return false; - } - // try to recover amount commitment information: amount & blinding factor if (!try_recover_amount_commitment_info(enote, - enote_ephemeral_pubkey, nominal_sender_receiver_secret_out, - jamtis_spend_pubkey, - k_view_balance, - d_view_received, - record_out.address_index, - s_generate_address, - balance_recovery_path, record_out.amount, record_out.amount_blinding_factor, enote_type_out)) @@ -348,12 +287,17 @@ static bool try_plain_core_balance_recovery_v1(const SpEnoteVariant &enote, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, SpIntermediateEnoteRecordV1 &record_out) { + // X_ir = d_ir D_e + crypto::x25519_pubkey x_ir; + crypto::x25519_scmul_key(d_identify_received, enote_ephemeral_pubkey, x_ir); + rct::key dummy_sender_receiver_secret; rct::key dummy_recipient_address_spendkey; jamtis::JamtisEnoteType dummy_enote_type; @@ -362,12 +306,12 @@ static bool try_plain_core_balance_recovery_v1(const SpEnoteVariant &enote, num_primary_view_tag_bits, input_context, jamtis_spend_pubkey, - crypto::null_skey, - d_view_received, - d_filter_assist, + lazy_scmul_key{d_filter_assist, enote_ephemeral_pubkey}, + x_ir.data, + lazy_make_x_ur_plain{jamtis_spend_pubkey, s_generate_address, record_out.address_index, + d_unlock_received, enote_ephemeral_pubkey}, s_generate_address, cipher_context, - BalanceRecoveryPath::PLAIN, dummy_sender_receiver_secret, dummy_recipient_address_spendkey, dummy_enote_type, @@ -375,33 +319,25 @@ static bool try_plain_core_balance_recovery_v1(const SpEnoteVariant &enote, } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- +template static bool try_complete_balance_recovery_v1(const SpEnoteVariant &enote, const crypto::x25519_pubkey &enote_ephemeral_pubkey, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, - const crypto::x25519_secret_key &d_filter_assist, + MakeXfa &&make_x_fa, // () -> jamtis::secret256_ptr_t functional object + const jamtis::secret256_ptr_t x_ir, + MakeXur &&make_x_ur, // (jamtis::address_index_t) -> jamtis::secret256_ptr_t functional object + const crypto::secret_key &k_generate_image, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, - const BalanceRecoveryPath balance_recovery_path, SpEnoteRecordV1 &record_out) { - // "Complete" balance recovery is the all stages of balance recovery after the primary view tag + // "complete" balance recovery is the all stages of balance recovery after the primary view tag // check for both plain and self-send enotes. We attempt to recover the following information // and fill in the corresponding fields of a full enote record: whether enote is owned, address // index, amount, amount blinding factor, enote type, enote view extensions, key image - if (balance_recovery_path == BalanceRecoveryPath::AUXILIARY_SELFSEND) - { - // test auxiliary self-send view tag - if (!jamtis::test_jamtis_auxiliary_view_tag(k_view_balance, - onetime_address_ref(enote), - view_tag_ref(enote))) - return false; - } - // attempt core balance recovery for given path rct::key nominal_sender_receiver_secret; rct::key recipient_address_spendkey; @@ -410,12 +346,11 @@ static bool try_complete_balance_recovery_v1(const SpEnoteVariant &enote, num_primary_view_tag_bits, input_context, jamtis_spend_pubkey, - k_view_balance, - d_view_received, - d_filter_assist, + make_x_fa, + x_ir, + make_x_ur, s_generate_address, cipher_context, - balance_recovery_path, nominal_sender_receiver_secret, recipient_address_spendkey, record_out.type, @@ -433,9 +368,9 @@ static bool try_complete_balance_recovery_v1(const SpEnoteVariant &enote, record_out.enote_view_extension_x, record_out.enote_view_extension_u); - // make key image: (k_u + k_m)/(k_x + k_vb) U + // make key image: (k_u + k_ps)/(k_x + k_gi) U make_seraphis_key_image_helper(jamtis_spend_pubkey, - k_view_balance, + k_generate_image, record_out.enote_view_extension_x, record_out.enote_view_extension_u, record_out.key_image); @@ -444,51 +379,17 @@ static bool try_complete_balance_recovery_v1(const SpEnoteVariant &enote, } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- -static bool try_complete_balance_recovery_multipath_v1(const SpEnoteVariant &enote, - const crypto::x25519_pubkey &enote_ephemeral_pubkey, - const std::uint8_t num_primary_view_tag_bits, - const rct::key &input_context, - const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, - const crypto::x25519_secret_key &d_filter_assist, - const crypto::secret_key &s_generate_address, - const jamtis::jamtis_address_tag_cipher_context &cipher_context, - const epee::span balance_recovery_paths, - SpEnoteRecordV1 &record_out) -{ - for (size_t i = 0; i < balance_recovery_paths.size(); ++i) - { - if (try_complete_balance_recovery_v1(enote, - enote_ephemeral_pubkey, - num_primary_view_tag_bits, - input_context, - jamtis_spend_pubkey, - k_view_balance, - d_view_received, - d_filter_assist, - s_generate_address, - cipher_context, - balance_recovery_paths[i], - record_out)) - return true; - } - - return false; -} -//------------------------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------------------------- bool try_get_basic_enote_record_v1(const SpEnoteVariant &enote, const crypto::x25519_pubkey &enote_ephemeral_pubkey, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, - const crypto::x25519_pubkey &dhe_fa, + const crypto::x25519_pubkey x_fa, SpBasicEnoteRecordV1 &basic_record_out) { // get a basic record // 1. check against primary view tag - if (!jamtis::test_jamtis_primary_view_tag(dhe_fa, + if (!jamtis::test_jamtis_primary_view_tag(x_fa.data, onetime_address_ref(enote), view_tag_ref(enote), num_primary_view_tag_bits)) @@ -498,7 +399,7 @@ bool try_get_basic_enote_record_v1(const SpEnoteVariant &enote, basic_record_out.enote = enote; basic_record_out.enote_ephemeral_pubkey = enote_ephemeral_pubkey; basic_record_out.input_context = input_context; - basic_record_out.passed_exclusive_check = true; + basic_record_out.primary_vt_matches = true; return true; } @@ -512,15 +413,15 @@ bool try_get_basic_enote_record_v1(const SpEnoteVariant &enote, { // compute DH derivation then get basic record - // D^d_fa = xr D^j_fa = d_fa D_e - crypto::x25519_pubkey dhe_fa; - crypto::x25519_scmul_key(d_filter_assist, enote_ephemeral_pubkey, dhe_fa); + // X_fa = xr D^j_fa = d_fa D_e + crypto::x25519_pubkey x_fa; + crypto::x25519_scmul_key(d_filter_assist, enote_ephemeral_pubkey, x_fa); return try_get_basic_enote_record_v1(enote, enote_ephemeral_pubkey, num_primary_view_tag_bits, input_context, - dhe_fa, + x_fa, basic_record_out); } //------------------------------------------------------------------------------------------------------------------- @@ -529,7 +430,8 @@ bool try_get_intermediate_enote_record_v1(const SpEnoteVariant &enote, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, @@ -550,7 +452,8 @@ bool try_get_intermediate_enote_record_v1(const SpEnoteVariant &enote, num_primary_view_tag_bits, input_context, jamtis_spend_pubkey, - d_view_received, + d_unlock_received, + d_identify_received, d_filter_assist, s_generate_address, cipher_context, @@ -562,7 +465,8 @@ bool try_get_intermediate_enote_record_v1(const SpEnoteVariant &enote, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, SpIntermediateEnoteRecordV1 &record_out) @@ -578,7 +482,8 @@ bool try_get_intermediate_enote_record_v1(const SpEnoteVariant &enote, num_primary_view_tag_bits, input_context, jamtis_spend_pubkey, - d_view_received, + d_unlock_received, + d_identify_received, d_filter_assist, s_generate_address, cipher_context, @@ -587,7 +492,8 @@ bool try_get_intermediate_enote_record_v1(const SpEnoteVariant &enote, //------------------------------------------------------------------------------------------------------------------- bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, @@ -595,7 +501,7 @@ bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_reco { // process basic record then get an intermediate record - if (!basic_record.passed_exclusive_check) + if (!basic_record.primary_vt_matches) return false; return try_plain_core_balance_recovery_v1(basic_record.enote, @@ -603,7 +509,8 @@ bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_reco basic_record.num_primary_view_tag_bits, basic_record.input_context, jamtis_spend_pubkey, - d_view_received, + d_unlock_received, + d_identify_received, d_filter_assist, s_generate_address, cipher_context, @@ -612,7 +519,8 @@ bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_reco //------------------------------------------------------------------------------------------------------------------- bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, SpIntermediateEnoteRecordV1 &record_out) @@ -625,7 +533,8 @@ bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_reco return try_get_intermediate_enote_record_v1(basic_record, jamtis_spend_pubkey, - d_view_received, + d_unlock_received, + d_identify_received, d_filter_assist, s_generate_address, cipher_context, @@ -634,36 +543,54 @@ bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_reco //------------------------------------------------------------------------------------------------------------------- bool try_get_enote_record_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, + const crypto::secret_key &s_view_balance, + const crypto::secret_key &k_generate_image, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, SpEnoteRecordV1 &record_out) { - constexpr BalanceRecoveryPath ALL_PATHS[] = { - BalanceRecoveryPath::PLAIN, - BalanceRecoveryPath::EXCLUSIVE_SELFSEND, - BalanceRecoveryPath::AUXILIARY_SELFSEND }; - - constexpr BalanceRecoveryPath AUX_PATH[] = { BalanceRecoveryPath::AUXILIARY_SELFSEND }; + lazy_scmul_key make_x_fa{d_filter_assist, basic_record.enote_ephemeral_pubkey}; - const auto paths_to_try = basic_record.passed_exclusive_check - ? epee::span(ALL_PATHS) - : epee::span(AUX_PATH); + if (basic_record.primary_vt_matches) + { + // X_ir = d_ir D_e + crypto::x25519_pubkey x_ir; + crypto::x25519_scmul_key(d_identify_received, basic_record.enote_ephemeral_pubkey, x_ir); + + if (try_complete_balance_recovery_v1(basic_record.enote, + basic_record.enote_ephemeral_pubkey, + basic_record.num_primary_view_tag_bits, + basic_record.input_context, + jamtis_spend_pubkey, + make_x_fa, + x_ir.data, + lazy_make_x_ur_plain{jamtis_spend_pubkey, s_generate_address, record_out.address_index, + d_unlock_received, basic_record.enote_ephemeral_pubkey}, + k_generate_image, + s_generate_address, + cipher_context, + record_out)) + return true; + } - return try_complete_balance_recovery_multipath_v1(basic_record.enote, - basic_record.enote_ephemeral_pubkey, - basic_record.num_primary_view_tag_bits, - basic_record.input_context, - jamtis_spend_pubkey, - k_view_balance, - d_view_received, - d_filter_assist, - s_generate_address, - cipher_context, - paths_to_try, - record_out); + if (try_complete_balance_recovery_v1(basic_record.enote, + basic_record.enote_ephemeral_pubkey, + basic_record.num_primary_view_tag_bits, + basic_record.input_context, + jamtis_spend_pubkey, + make_x_fa, + reinterpret_cast(s_view_balance.data), + [&s_view_balance]() { return reinterpret_cast(s_view_balance.data); }, + k_generate_image, + s_generate_address, + cipher_context, + record_out)) + return true; + + return false; } //------------------------------------------------------------------------------------------------------------------- bool try_get_enote_record_v1(const SpEnoteVariant &enote, @@ -671,55 +598,47 @@ bool try_get_enote_record_v1(const SpEnoteVariant &enote, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, SpEnoteRecordV1 &record_out) { - // 1. generate account secrets tree from k_vb - crypto::x25519_secret_key d_view_received; + // generate account secrets tree from s_vb + crypto::secret_key k_generate_image; + crypto::x25519_secret_key d_unlock_received; + crypto::x25519_secret_key d_identify_received; crypto::x25519_secret_key d_filter_assist; crypto::secret_key s_generate_address; crypto::secret_key s_cipher_tag; - jamtis::make_jamtis_viewreceived_key(k_view_balance, d_view_received); - jamtis::make_jamtis_filterassist_key(d_view_received, d_filter_assist); - jamtis::make_jamtis_generateaddress_secret(d_view_received, s_generate_address); + jamtis::make_jamtis_generateimage_key(s_view_balance, k_generate_image); + jamtis::make_jamtis_unlockreceived_key(s_view_balance, d_unlock_received); + jamtis::make_jamtis_identifyreceived_key(s_view_balance, d_identify_received); + jamtis::make_jamtis_filterassist_key(s_view_balance, d_filter_assist); + jamtis::make_jamtis_generateaddress_secret(s_view_balance, s_generate_address); jamtis::make_jamtis_ciphertag_secret(s_generate_address, s_cipher_tag); const jamtis::jamtis_address_tag_cipher_context cipher_context{s_cipher_tag}; - // 2. do primary DH and primary view tag check - const bool view_tag_match = jamtis::test_jamtis_primary_view_tag(d_filter_assist, - enote_ephemeral_pubkey, - onetime_address_ref(enote), - view_tag_ref(enote), - num_primary_view_tag_bits); - - // 3. if the primary view tag matched, try scanning for plain and exclusive self-send enotes - constexpr BalanceRecoveryPath ALL_PATHS[] = { - BalanceRecoveryPath::AUXILIARY_SELFSEND, - BalanceRecoveryPath::PLAIN, - BalanceRecoveryPath::EXCLUSIVE_SELFSEND}; - - const epee::span paths_to_check(ALL_PATHS, - view_tag_match ? 3 : 1); + // manually construct a fake basic record, pretending that the primary view tag matches + const SpBasicEnoteRecordV1 basic_record{.enote = enote, + .enote_ephemeral_pubkey = enote_ephemeral_pubkey, + .num_primary_view_tag_bits = num_primary_view_tag_bits, + .input_context = input_context, + .primary_vt_matches = true}; - // 4. if the other paths fail, always try auxiliary scanning since we have no tx information - return try_complete_balance_recovery_multipath_v1(enote, - enote_ephemeral_pubkey, - num_primary_view_tag_bits, - input_context, + return try_get_enote_record_v1(basic_record, jamtis_spend_pubkey, - k_view_balance, - d_view_received, + s_view_balance, + k_generate_image, + d_unlock_received, + d_identify_received, d_filter_assist, s_generate_address, cipher_context, - paths_to_check, record_out); } //------------------------------------------------------------------------------------------------------------------- bool try_get_enote_record_v1(const SpIntermediateEnoteRecordV1 &intermediate_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, SpEnoteRecordV1 &record_out) { return try_get_enote_record_v1(intermediate_record.enote, @@ -727,38 +646,44 @@ bool try_get_enote_record_v1(const SpIntermediateEnoteRecordV1 &intermediate_rec intermediate_record.num_primary_view_tag_bits, intermediate_record.input_context, jamtis_spend_pubkey, - k_view_balance, + s_view_balance, record_out); } //------------------------------------------------------------------------------------------------------------------- bool try_get_enote_record_plain_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, + const crypto::secret_key &s_view_balance, + const crypto::secret_key &k_generate_image, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, SpEnoteRecordV1 &record_out) { - if (!basic_record.passed_exclusive_check) + if (!basic_record.primary_vt_matches) return false; - jamtis::JamtisEnoteType enote_type{}; - if (!try_complete_balance_recovery_v1(basic_record.enote, + // X_ir = d_ir D_e + crypto::x25519_pubkey x_ir; + crypto::x25519_scmul_key(d_identify_received, basic_record.enote_ephemeral_pubkey, x_ir); + + if (try_complete_balance_recovery_v1(basic_record.enote, basic_record.enote_ephemeral_pubkey, basic_record.num_primary_view_tag_bits, basic_record.input_context, jamtis_spend_pubkey, - k_view_balance, - d_view_received, - d_filter_assist, + lazy_scmul_key{d_filter_assist, basic_record.enote_ephemeral_pubkey}, + x_ir.data, + lazy_make_x_ur_plain{jamtis_spend_pubkey, s_generate_address, record_out.address_index, + d_unlock_received, basic_record.enote_ephemeral_pubkey}, + k_generate_image, s_generate_address, cipher_context, - BalanceRecoveryPath::PLAIN, record_out)) - return false; + return true; - return enote_type == jamtis::JamtisEnoteType::PLAIN; + return record_out.type == jamtis::JamtisEnoteType::PLAIN; } //------------------------------------------------------------------------------------------------------------------- } //namespace sp diff --git a/src/seraphis_main/enote_record_utils.h b/src/seraphis_main/enote_record_utils.h index fecc0b01645..491eec20747 100644 --- a/src/seraphis_main/enote_record_utils.h +++ b/src/seraphis_main/enote_record_utils.h @@ -55,7 +55,7 @@ namespace sp * param: enote_ephemeral_pubkey - * param: num_primary_view_tag_bits - npbits * param: input_context - -* param: dhe_fa - D^d_fa = xr D^j_fa = d_fa D_e +* param: x_fa - X_fa * param: d_filter_assist - * outparam: basic_record_out - * return: true if extraction succeeded @@ -64,7 +64,7 @@ bool try_get_basic_enote_record_v1(const SpEnoteVariant &enote, const crypto::x25519_pubkey &enote_ephemeral_pubkey, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, - const crypto::x25519_pubkey &dhe_fa, + const crypto::x25519_pubkey x_fa, SpBasicEnoteRecordV1 &basic_record_out); bool try_get_basic_enote_record_v1(const SpEnoteVariant &enote, const crypto::x25519_pubkey &enote_ephemeral_pubkey, @@ -79,7 +79,8 @@ bool try_get_basic_enote_record_v1(const SpEnoteVariant &enote, * param: num_primary_view_tag_bits - npbits * param: input_context - * param: jamtis_spend_pubkey - -* param: d_view_received - +* param: d_unlock_received - +* param: d_identify_received - * param: d_filter_assist - * param: s_generate_address - * param: cipher_context - @@ -91,7 +92,8 @@ bool try_get_intermediate_enote_record_v1(const SpEnoteVariant &enote, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, @@ -101,20 +103,23 @@ bool try_get_intermediate_enote_record_v1(const SpEnoteVariant &enote, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, SpIntermediateEnoteRecordV1 &record_out); bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, SpIntermediateEnoteRecordV1 &record_out); bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, SpIntermediateEnoteRecordV1 &record_out); @@ -123,8 +128,10 @@ bool try_get_intermediate_enote_record_v1(const SpBasicEnoteRecordV1 &basic_reco */ bool try_get_enote_record_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, + const crypto::secret_key &s_view_balance, + const crypto::secret_key &k_generate_image, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, @@ -134,16 +141,18 @@ bool try_get_enote_record_v1(const SpEnoteVariant &enote, const std::uint8_t num_primary_view_tag_bits, const rct::key &input_context, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, SpEnoteRecordV1 &record_out); bool try_get_enote_record_v1(const SpIntermediateEnoteRecordV1 &intermediate_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, SpEnoteRecordV1 &record_out); bool try_get_enote_record_plain_v1(const SpBasicEnoteRecordV1 &basic_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, + const crypto::secret_key &s_view_balance, + const crypto::secret_key &k_generate_image, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, diff --git a/src/seraphis_main/enote_record_utils_legacy.cpp b/src/seraphis_main/enote_record_utils_legacy.cpp index 84743cc5369..78ddd4dfcd7 100644 --- a/src/seraphis_main/enote_record_utils_legacy.cpp +++ b/src/seraphis_main/enote_record_utils_legacy.cpp @@ -165,8 +165,8 @@ static bool try_get_amount_commitment_information_v1(const rct::xmr_amount &enot //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- static bool try_get_amount_commitment_information_v2(const rct::key &amount_commitment, - const rct::key &encoded_amount_mask, - const rct::key &encoded_amount, + const rct::key &encrypted_amount_mask, + const rct::key &encrypted_amount, const std::uint64_t tx_output_index, const crypto::key_derivation &sender_receiver_DH_derivation, hw::device &hwdev, @@ -180,8 +180,8 @@ static bool try_get_amount_commitment_information_v2(const rct::key &amount_comm // 2. recover the amount mask and amount if (!try_get_legacy_amount_v1(amount_commitment, sender_receiver_secret, - encoded_amount_mask, - encoded_amount, + encrypted_amount_mask, + encrypted_amount, hwdev, amount_blinding_factor_out, amount_out)) @@ -192,7 +192,7 @@ static bool try_get_amount_commitment_information_v2(const rct::key &amount_comm //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- static bool try_get_amount_commitment_information_v3(const rct::key &amount_commitment, - const jamtis::encoded_amount_t &encoded_amount, + const jamtis::encrypted_amount_t &encrypted_amount, const std::uint64_t tx_output_index, const crypto::key_derivation &sender_receiver_DH_derivation, hw::device &hwdev, @@ -206,7 +206,7 @@ static bool try_get_amount_commitment_information_v3(const rct::key &amount_comm // 2. recover the amount mask and amount if (!try_get_legacy_amount_v2(amount_commitment, sender_receiver_secret, - encoded_amount, + encrypted_amount, hwdev, amount_blinding_factor_out, amount_out)) @@ -232,8 +232,8 @@ static bool try_get_amount_commitment_information(const LegacyEnoteVariant &enot else if (const LegacyEnoteV2 *enote_ptr = enote.try_unwrap()) { return try_get_amount_commitment_information_v2(enote_ptr->amount_commitment, - enote_ptr->encoded_amount_blinding_factor, - enote_ptr->encoded_amount, + enote_ptr->encrypted_amount_blinding_factor, + enote_ptr->encrypted_amount, tx_output_index, sender_receiver_DH_derivation, hwdev, @@ -243,7 +243,7 @@ static bool try_get_amount_commitment_information(const LegacyEnoteVariant &enot else if (const LegacyEnoteV3 *enote_ptr = enote.try_unwrap()) { return try_get_amount_commitment_information_v3(enote_ptr->amount_commitment, - enote_ptr->encoded_amount, + enote_ptr->encrypted_amount, tx_output_index, sender_receiver_DH_derivation, hwdev, @@ -259,7 +259,7 @@ static bool try_get_amount_commitment_information(const LegacyEnoteVariant &enot else if (const LegacyEnoteV5 *enote_ptr = enote.try_unwrap()) { return try_get_amount_commitment_information_v3(enote_ptr->amount_commitment, - enote_ptr->encoded_amount, + enote_ptr->encrypted_amount, tx_output_index, sender_receiver_DH_derivation, hwdev, @@ -368,14 +368,14 @@ bool try_get_legacy_basic_enote_record(const LegacyEnoteVariant &enote, } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- -static bool is_encoded_amount_v1(const cryptonote::transaction &tx) +static bool is_encrypted_amount_v1(const cryptonote::transaction &tx) { return tx.rct_signatures.type == rct::RCTTypeFull || tx.rct_signatures.type == rct::RCTTypeSimple || tx.rct_signatures.type == rct::RCTTypeBulletproof; } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- -static bool is_encoded_amount_v2(const cryptonote::transaction &tx) +static bool is_encrypted_amount_v2(const cryptonote::transaction &tx) { return tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus; @@ -393,7 +393,7 @@ static bool is_legacy_enote_v1(const cryptonote::transaction &tx, const cryptono static bool is_legacy_enote_v2(const cryptonote::transaction &tx, const cryptonote::tx_out &out) { // Encrypted amount v1, no view tag - return tx.version == 2 && !cryptonote::is_coinbase(tx) && is_encoded_amount_v1(tx) && + return tx.version == 2 && !cryptonote::is_coinbase(tx) && is_encrypted_amount_v1(tx) && out.target.type() == typeid(cryptonote::txout_to_key); } //------------------------------------------------------------------------------------------------------------------- @@ -401,7 +401,7 @@ static bool is_legacy_enote_v2(const cryptonote::transaction &tx, const cryptono static bool is_legacy_enote_v3(const cryptonote::transaction &tx, const cryptonote::tx_out &out) { // Encrypted amount v2, no view tag - return tx.version == 2 && !cryptonote::is_coinbase(tx) && is_encoded_amount_v2(tx) && + return tx.version == 2 && !cryptonote::is_coinbase(tx) && is_encrypted_amount_v2(tx) && out.target.type() == typeid(cryptonote::txout_to_key); } //------------------------------------------------------------------------------------------------------------------- @@ -417,7 +417,7 @@ static bool is_legacy_enote_v4(const cryptonote::transaction &tx, const cryptono static bool is_legacy_enote_v5(const cryptonote::transaction &tx, const cryptonote::tx_out &out) { // Encrypted amount v2, view tag - return tx.version == 2 && !cryptonote::is_coinbase(tx) && is_encoded_amount_v2(tx) && + return tx.version == 2 && !cryptonote::is_coinbase(tx) && is_encrypted_amount_v2(tx) && out.target.type() == typeid(cryptonote::txout_to_tagged_key); } //------------------------------------------------------------------------------------------------------------------- @@ -465,9 +465,9 @@ static bool try_out_to_legacy_enote_v2(const cryptonote::transaction &tx, /// C enote_v2.amount_commitment = tx.rct_signatures.outPk[output_index].mask; /// enc(x) - enote_v2.encoded_amount_blinding_factor = tx.rct_signatures.ecdhInfo[output_index].mask; + enote_v2.encrypted_amount_blinding_factor = tx.rct_signatures.ecdhInfo[output_index].mask; /// enc(a) - enote_v2.encoded_amount = tx.rct_signatures.ecdhInfo[output_index].amount; + enote_v2.encrypted_amount = tx.rct_signatures.ecdhInfo[output_index].amount; enote_out = std::move(enote_v2); return true; @@ -494,9 +494,9 @@ static bool try_out_to_legacy_enote_v3(const cryptonote::transaction &tx, /// C enote_v3.amount_commitment = tx.rct_signatures.outPk[output_index].mask; /// enc(a) - constexpr size_t byte_size = sizeof(enote_v3.encoded_amount); + constexpr size_t byte_size = sizeof(enote_v3.encrypted_amount); static_assert(byte_size <= sizeof(tx.rct_signatures.ecdhInfo[output_index].amount.bytes)); - memcpy(&enote_v3.encoded_amount, &tx.rct_signatures.ecdhInfo[output_index].amount.bytes, byte_size); + memcpy(&enote_v3.encrypted_amount, &tx.rct_signatures.ecdhInfo[output_index].amount.bytes, byte_size); enote_out = std::move(enote_v3); return true; @@ -548,9 +548,9 @@ static bool try_out_to_legacy_enote_v5(const cryptonote::transaction &tx, /// C enote_v5.amount_commitment = tx.rct_signatures.outPk[output_index].mask; /// enc(a) - constexpr size_t byte_size = sizeof(enote_v5.encoded_amount); + constexpr size_t byte_size = sizeof(enote_v5.encrypted_amount); static_assert(byte_size <= sizeof(tx.rct_signatures.ecdhInfo[output_index].amount.bytes)); - memcpy(&enote_v5.encoded_amount, &tx.rct_signatures.ecdhInfo[output_index].amount.bytes, byte_size); + memcpy(&enote_v5.encrypted_amount, &tx.rct_signatures.ecdhInfo[output_index].amount.bytes, byte_size); /// view_tag enote_v5.view_tag = *cryptonote::get_output_view_tag(tx.vout[output_index]); diff --git a/src/seraphis_main/scan_balance_recovery_utils.cpp b/src/seraphis_main/scan_balance_recovery_utils.cpp index fb9eb28e54a..b21781938cb 100644 --- a/src/seraphis_main/scan_balance_recovery_utils.cpp +++ b/src/seraphis_main/scan_balance_recovery_utils.cpp @@ -390,7 +390,7 @@ std::uint64_t filter_assist_scan_64(const crypto::x25519_secret_key &d_filter_as // b. filter-assist scan the enote (in try block in case enote is malformed) try { - if (jamtis::test_jamtis_primary_view_tag(temp_DH_derivation, + if (jamtis::test_jamtis_primary_view_tag(temp_DH_derivation.data, onetime_address_ref(enotes[enote_index]), view_tag_ref(enotes[enote_index]), num_primary_view_tag_bits)) @@ -471,7 +471,7 @@ bool try_find_sp_enotes_in_tx(const crypto::x25519_secret_key &d_filter_assist, .enote_ephemeral_pubkey = *pephemeral_pubkey, .num_primary_view_tag_bits = tx_supplement.num_primary_view_tag_bits, .input_context = input_context, - .passed_exclusive_check = enote_passed_exclusive_check[enote_index], + .primary_vt_matches = enote_passed_exclusive_check[enote_index], }; basic_records_in_tx_out.push_back(SpContextualBasicEnoteRecordV1{ @@ -643,7 +643,8 @@ void process_chunk_full_legacy(const rct::key &legacy_base_spend_pubkey, } //------------------------------------------------------------------------------------------------------------------- void process_chunk_intermediate_sp(const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, @@ -671,7 +672,8 @@ void process_chunk_intermediate_sp(const rct::key &jamtis_spend_pubkey, if (!try_get_intermediate_enote_record_v1( sp_contextual_basic_record->record, jamtis_spend_pubkey, - d_view_received, + d_unlock_received, + d_identify_received, d_filter_assist, s_generate_address, cipher_context, @@ -688,8 +690,10 @@ void process_chunk_intermediate_sp(const rct::key &jamtis_spend_pubkey, } //------------------------------------------------------------------------------------------------------------------- void process_chunk_full_sp(const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, + const crypto::secret_key &s_view_balance, + const crypto::secret_key &k_generate_image, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, @@ -754,8 +758,10 @@ void process_chunk_full_sp(const rct::key &jamtis_spend_pubkey, if (!try_get_enote_record_v1( sp_contextual_basic_record->record, jamtis_spend_pubkey, - k_view_balance, - d_view_received, + s_view_balance, + k_generate_image, + d_unlock_received, + d_identify_received, d_filter_assist, s_generate_address, cipher_context, diff --git a/src/seraphis_main/scan_balance_recovery_utils.h b/src/seraphis_main/scan_balance_recovery_utils.h index 03afdb2ff26..0efe9b03523 100644 --- a/src/seraphis_main/scan_balance_recovery_utils.h +++ b/src/seraphis_main/scan_balance_recovery_utils.h @@ -194,7 +194,8 @@ void process_chunk_full_legacy(const rct::key &legacy_base_spend_pubkey, /** * brief: process_chunk_intermediate_sp - process a chunk of contextual basic records with seraphis {kx_ua, kx_fr, s_ga} * param: jamtis_spend_pubkey - -* param: d_view_received - d_vr +* param: d_unlock_received - d_ur +* param: d_identify_received - d_ir * param: d_filter_assist - d_fa * param: s_generate_address - * param: cipher_context - @@ -202,7 +203,8 @@ void process_chunk_full_legacy(const rct::key &legacy_base_spend_pubkey, * outparam: found_enote_records_out - [ Ko : legacy contextual intermediate enote record ] */ void process_chunk_intermediate_sp(const rct::key &jamtis_spend_pubkey, - const crypto::x25519_secret_key &d_view_received, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, @@ -211,8 +213,9 @@ void process_chunk_intermediate_sp(const rct::key &jamtis_spend_pubkey, /** * brief: process_chunk_full_sp - process a chunk of contextual basic/auxiliary records with seraphis view-balance key * param: jamtis_spend_pubkey - -* param: k_view_balance - -* param: d_view_received - +* param: s_view_balance - +* param: d_unlock_received - +* param: d_identify_received - * param: d_filter_assist - * param: s_generate_address - * param: cipher_context - @@ -223,8 +226,10 @@ void process_chunk_intermediate_sp(const rct::key &jamtis_spend_pubkey, * outparam: legacy_key_images_in_sp_selfsends_out - [ legacy KI : spent context ] */ void process_chunk_full_sp(const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, - const crypto::x25519_secret_key &d_view_received, + const crypto::secret_key &s_view_balance, + const crypto::secret_key &k_generate_image, + const crypto::x25519_secret_key &d_unlock_received, + const crypto::x25519_secret_key &d_identify_received, const crypto::x25519_secret_key &d_filter_assist, const crypto::secret_key &s_generate_address, const jamtis::jamtis_address_tag_cipher_context &cipher_context, diff --git a/src/seraphis_main/sp_knowledge_proof_utils.cpp b/src/seraphis_main/sp_knowledge_proof_utils.cpp index b11a33045aa..1b5eed5853e 100644 --- a/src/seraphis_main/sp_knowledge_proof_utils.cpp +++ b/src/seraphis_main/sp_knowledge_proof_utils.cpp @@ -149,42 +149,46 @@ void make_address_ownership_proof_v1(const rct::key &message, } //------------------------------------------------------------------------------------------------------------------- void make_address_ownership_proof_v1(const rct::key &message, - const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &k_prove_spend, + const crypto::secret_key &s_view_balance, AddressOwnershipProofV1 &proof_out) { // for address ownership of K_s - // 1. prepare K_s = k_vb X + k_m U + // 1. make generate image key: k_gi + H_32[s_vb]() + crypto::secret_key k_generate_image; + jamtis::make_jamtis_generateimage_key(s_view_balance, k_generate_image); + + // 2. prepare K_s = k_gi X + k_ps U rct::key jamtis_spend_pubkey; - make_seraphis_spendkey(k_view_balance, sp_spend_privkey, jamtis_spend_pubkey); + make_seraphis_spendkey(k_generate_image, k_prove_spend, jamtis_spend_pubkey); - // 2. finish the proof + // 3. finish the proof make_address_ownership_proof_v1(message, jamtis_spend_pubkey, rct::rct2sk(rct::zero()), - k_view_balance, - sp_spend_privkey, + s_view_balance, + k_prove_spend, proof_out); } //------------------------------------------------------------------------------------------------------------------- void make_address_ownership_proof_v1(const rct::key &message, - const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &k_prove_spend, + const crypto::secret_key &s_view_balance, const jamtis::address_index_t &j, AddressOwnershipProofV1 &proof_out) { // for address ownership of K^j_s // 1. prepare privkey - crypto::x25519_secret_key d_view_received; + crypto::secret_key k_generate_image; crypto::secret_key s_generate_address; - jamtis::make_jamtis_viewreceived_key(k_view_balance, d_view_received); - jamtis::make_jamtis_generateaddress_secret(d_view_received, s_generate_address); + jamtis::make_jamtis_generateimage_key(s_view_balance, k_generate_image); + jamtis::make_jamtis_generateaddress_secret(s_view_balance, s_generate_address); - // 2. prepare K_s = k_vb X + k_m U + // 2. prepare K_s = k_gi X + k_ps U rct::key jamtis_spend_pubkey; - make_seraphis_spendkey(k_view_balance, sp_spend_privkey, jamtis_spend_pubkey); + make_seraphis_spendkey(k_generate_image, k_prove_spend, jamtis_spend_pubkey); // 3. prepare address privkey components // a. x = k^j_g @@ -194,12 +198,12 @@ void make_address_ownership_proof_v1(const rct::key &message, // b. y = k^j_x + k_vb crypto::secret_key y; jamtis::make_jamtis_spendkey_extension_x(jamtis_spend_pubkey, s_generate_address, j, y); //k^j_x - sc_add(to_bytes(y), to_bytes(k_view_balance), to_bytes(y)); //+ k_vb + sc_add(to_bytes(y), to_bytes(s_view_balance), to_bytes(y)); //+ k_vb // c. z = k^j_u + k_m crypto::secret_key z; jamtis::make_jamtis_spendkey_extension_u(jamtis_spend_pubkey, s_generate_address, j, z); //k^j_u - sc_add(to_bytes(z), to_bytes(sp_spend_privkey), to_bytes(z)); //+ k_m + sc_add(to_bytes(z), to_bytes(k_generate_image), to_bytes(z)); //+ k_m // 4. compute address // K^j_s = x G + y X + z U @@ -249,7 +253,7 @@ void make_address_index_proof_v1(const rct::key &jamtis_spend_pubkey, // 2. compute K^j_s rct::key addr_Ks; - jamtis::make_jamtis_address_spend_key(jamtis_spend_pubkey, s_generate_address, j, addr_Ks); + jamtis::make_jamtis_address_spend_key_sp(jamtis_spend_pubkey, s_generate_address, j, addr_Ks); // 3. assemble the full proof proof_out = AddressIndexProofV1{ @@ -331,23 +335,34 @@ void make_enote_ownership_proof_v1_sender_plain(const crypto::x25519_secret_key jamtis::make_jamtis_enote_ephemeral_pubkey(enote_ephemeral_privkey, recipient_destination.addr_Dbase, enote_ephemeral_pubkey); + + // 2. prepare X_fa, X_ir, and X_ur + crypto::x25519_pubkey x_fa; + crypto::x25519_scmul_key(enote_ephemeral_privkey, recipient_destination.addr_Dfa, x_fa); - // 2. prepare the sender-receiver secret + crypto::x25519_pubkey x_ir; + crypto::x25519_scmul_key(enote_ephemeral_privkey, recipient_destination.addr_Dfa, x_ir); + + crypto::x25519_pubkey x_ur; + crypto::x25519_scmul_base(enote_ephemeral_privkey, x_ur); + + // 3. prepare the sender-receiver secret rct::key sender_receiver_secret; - jamtis::make_jamtis_sender_receiver_secret_plain(enote_ephemeral_privkey, - recipient_destination.addr_Dvr, + jamtis::make_jamtis_sender_receiver_secret(x_fa.data, + x_ir.data, + x_ur.data, enote_ephemeral_pubkey, input_context, sender_receiver_secret); - // 3. complete the proof + // 4. complete the proof make_enote_ownership_proof_v1(recipient_destination.addr_Ks, sender_receiver_secret, amount_commitment, onetime_address, proof_out); - // 4. verify that the proof was created successfully + // 5. verify that the proof was created successfully // - will fail if the enote is a jamtis selfsend type CHECK_AND_ASSERT_THROW_MES(verify_enote_ownership_proof_v1(proof_out, amount_commitment, onetime_address), "make enote ownership proof (v1 sender plain): failed to make proof."); @@ -356,7 +371,7 @@ void make_enote_ownership_proof_v1_sender_plain(const crypto::x25519_secret_key void make_enote_ownership_proof_v1_sender_selfsend(const crypto::x25519_pubkey &enote_ephemeral_pubkey, const rct::key &jamtis_address_spend_key, const rct::key &input_context, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, const jamtis::JamtisSelfSendType self_send_type, const rct::key &amount_commitment, const rct::key &onetime_address, @@ -364,7 +379,7 @@ void make_enote_ownership_proof_v1_sender_selfsend(const crypto::x25519_pubkey & { // 1. prepare the sender-receiver secret rct::key sender_receiver_secret; - jamtis::make_jamtis_sender_receiver_secret_selfsend(k_view_balance, + jamtis::make_jamtis_sender_receiver_secret_selfsend(s_view_balance, enote_ephemeral_pubkey, input_context, jamtis::is_jamtis_auxiliary_selfsend_type(self_send_type), @@ -385,13 +400,13 @@ void make_enote_ownership_proof_v1_sender_selfsend(const crypto::x25519_pubkey & //------------------------------------------------------------------------------------------------------------------- void make_enote_ownership_proof_v1_receiver(const SpEnoteRecordV1 &enote_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, EnoteOwnershipProofV1 &proof_out) { // 1. helper privkeys crypto::x25519_secret_key d_view_received; crypto::secret_key s_generate_address; - jamtis::make_jamtis_viewreceived_key(k_view_balance, d_view_received); + jamtis::make_jamtis_viewreceived_key(s_view_balance, d_view_received); jamtis::make_jamtis_generateaddress_secret(d_view_received, s_generate_address); // 2. get the owning address's spendkey K^j_s @@ -407,7 +422,7 @@ void make_enote_ownership_proof_v1_receiver(const SpEnoteRecordV1 &enote_record, if (jamtis::try_get_jamtis_self_send_type(enote_record.type, self_send_type)) { - jamtis::make_jamtis_sender_receiver_secret_selfsend(k_view_balance, + jamtis::make_jamtis_sender_receiver_secret_selfsend(s_view_balance, enote_record.enote_ephemeral_pubkey, enote_record.input_context, jamtis::is_jamtis_auxiliary_selfsend_type(self_send_type), @@ -448,7 +463,7 @@ bool verify_enote_ownership_proof_v1(const EnoteOwnershipProofV1 &proof, // 2. reproduce the onetime address rct::key reproduced_Ko; - jamtis::make_jamtis_onetime_address(proof.addr_Ks, proof.q, proof.C, reproduced_Ko); + jamtis::make_jamtis_onetime_address_sp(proof.addr_Ks, proof.q, proof.C, reproduced_Ko); // 3. check the reproduced onetime address matches the proof if (!(proof.Ko == reproduced_Ko)) @@ -510,12 +525,12 @@ void make_enote_key_image_proof_v1(const rct::key &onetime_address, //------------------------------------------------------------------------------------------------------------------- void make_enote_key_image_proof_v1(const SpEnoteRecordV1 &enote_record, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, EnoteKeyImageProofV1 &proof_out) { // 1. y = k_x + k_vb crypto::secret_key y; - sc_add(to_bytes(y), to_bytes(enote_record.enote_view_extension_x), to_bytes(k_view_balance)); + sc_add(to_bytes(y), to_bytes(enote_record.enote_view_extension_x), to_bytes(s_view_balance)); // 2. z = k_u + k_m crypto::secret_key z; @@ -557,7 +572,7 @@ bool verify_enote_key_image_proof_v1(const EnoteKeyImageProofV1 &proof, //------------------------------------------------------------------------------------------------------------------- void make_enote_unspent_proof_v1(const SpEnoteRecordV1 &enote_record, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, const crypto::key_image &test_KI, EnoteUnspentProofV1 &proof_out) { @@ -568,7 +583,7 @@ void make_enote_unspent_proof_v1(const SpEnoteRecordV1 &enote_record, // b. ko_x = (k_x + k_vb) crypto::secret_key kox_skey; - sc_add(to_bytes(kox_skey), to_bytes(enote_record.enote_view_extension_x), to_bytes(k_view_balance)); + sc_add(to_bytes(kox_skey), to_bytes(enote_record.enote_view_extension_x), to_bytes(s_view_balance)); // c. ko_u = (k_u + k_m) crypto::secret_key kou_skey; @@ -673,7 +688,7 @@ bool verify_enote_unspent_proof_v1(const EnoteUnspentProofV1 &proof, void make_tx_funded_proof_v1(const rct::key &message, const SpEnoteRecordV1 &enote_record, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, TxFundedProofV1 &proof_out) { // 1. prepare a masked version of our enote's onetime address @@ -689,7 +704,7 @@ void make_tx_funded_proof_v1(const rct::key &message, // b. y = k_x + k_vb crypto::secret_key y; - sc_add(to_bytes(y), to_bytes(enote_record.enote_view_extension_x), to_bytes(k_view_balance)); + sc_add(to_bytes(y), to_bytes(enote_record.enote_view_extension_x), to_bytes(s_view_balance)); // c. z = k_u + k_m crypto::secret_key z; @@ -771,14 +786,14 @@ void make_reserved_enote_proof_v1(const EnoteOwnershipProofV1 &enote_ownership_p void make_reserved_enote_proof_v1(const SpContextualEnoteRecordV1 &contextual_record, const rct::key &jamtis_spend_pubkey, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, ReservedEnoteProofV1 &proof_out) { // 1. make enote ownership proof EnoteOwnershipProofV1 enote_ownership_proof; make_enote_ownership_proof_v1_receiver(contextual_record.record, jamtis_spend_pubkey, - k_view_balance, + s_view_balance, enote_ownership_proof); // 2. make amount proof @@ -792,7 +807,7 @@ void make_reserved_enote_proof_v1(const SpContextualEnoteRecordV1 &contextual_re EnoteKeyImageProofV1 key_image_proof; make_enote_key_image_proof_v1(contextual_record.record, sp_spend_privkey, - k_view_balance, + s_view_balance, key_image_proof); // 4. complete full proof @@ -865,7 +880,7 @@ void make_reserve_proof_v1(const rct::key &message, const std::vector &reserved_enote_records, const rct::key &jamtis_spend_pubkey, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, ReserveProofV1 &proof_out) { // 1. make randomized indices into the records @@ -895,7 +910,7 @@ void make_reserve_proof_v1(const rct::key &message, make_reserved_enote_proof_v1(record, jamtis_spend_pubkey, sp_spend_privkey, - k_view_balance, + s_view_balance, tools::add_element(reserved_enote_proofs)); // d. save the address index @@ -910,7 +925,7 @@ void make_reserve_proof_v1(const rct::key &message, { make_address_ownership_proof_v1(message, sp_spend_privkey, - k_view_balance, + s_view_balance, j, tools::add_element(address_ownership_proofs)); } diff --git a/src/seraphis_main/sp_knowledge_proof_utils.h b/src/seraphis_main/sp_knowledge_proof_utils.h index b0e18c82bf0..6b6cdbaa9bb 100644 --- a/src/seraphis_main/sp_knowledge_proof_utils.h +++ b/src/seraphis_main/sp_knowledge_proof_utils.h @@ -70,12 +70,12 @@ void make_address_ownership_proof_v1(const rct::key &message, const crypto::secret_key &z, AddressOwnershipProofV1 &proof_out); void make_address_ownership_proof_v1(const rct::key &message, //for K_s - const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &k_prove_spend, + const crypto::secret_key &s_view_balance, AddressOwnershipProofV1 &proof_out); void make_address_ownership_proof_v1(const rct::key &message, //for K^j_s - const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &k_prove_spend, + const crypto::secret_key &s_view_balance, const jamtis::address_index_t &j, AddressOwnershipProofV1 &proof_out); /** @@ -128,14 +128,14 @@ void make_enote_ownership_proof_v1_sender_plain(const crypto::x25519_secret_key void make_enote_ownership_proof_v1_sender_selfsend(const crypto::x25519_pubkey &enote_ephemeral_pubkey, const rct::key &jamtis_address_spend_key, const rct::key &input_context, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, const jamtis::JamtisSelfSendType self_send_type, const rct::key &amount_commitment, const rct::key &onetime_address, EnoteOwnershipProofV1 &proof_out); void make_enote_ownership_proof_v1_receiver(const SpEnoteRecordV1 &enote_record, const rct::key &jamtis_spend_pubkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, EnoteOwnershipProofV1 &proof_out); /** * brief: verify enote ownership proof @@ -180,7 +180,7 @@ void make_enote_key_image_proof_v1(const rct::key &onetime_address, EnoteKeyImageProofV1 &proof_out); void make_enote_key_image_proof_v1(const SpEnoteRecordV1 &enote_record, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, EnoteKeyImageProofV1 &proof_out); /** * brief: verify enote key image proof @@ -196,13 +196,13 @@ bool verify_enote_key_image_proof_v1(const EnoteKeyImageProofV1 &proof, * brief: make an enote unspent proof * param: enote_record - record of the enote for this proof * param: sp_spend_privkey - k_m -* param: k_view_balance - k_vb +* param: s_view_balance - k_vb * param: test_KI - key image this proof shows does NOT correspond to the proof enote * outparam: proof_out - proof created */ void make_enote_unspent_proof_v1(const SpEnoteRecordV1 &enote_record, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, const crypto::key_image &test_KI, EnoteUnspentProofV1 &proof_out); /** @@ -227,7 +227,7 @@ bool verify_enote_unspent_proof_v1(const EnoteUnspentProofV1 &proof, void make_tx_funded_proof_v1(const rct::key &message, const SpEnoteRecordV1 &enote_record, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, TxFundedProofV1 &proof_out); /** * brief: verify funded tx proof @@ -274,7 +274,7 @@ void make_reserved_enote_proof_v1(const EnoteOwnershipProofV1 &enote_ownership_p void make_reserved_enote_proof_v1(const SpContextualEnoteRecordV1 &contextual_record, const rct::key &jamtis_spend_pubkey, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, ReservedEnoteProofV1 &proof_out); /** * brief: verify reserved enote proof @@ -301,14 +301,14 @@ bool reserved_enote_is_reserved_v1(const ReservedEnoteProofV1 &proof, const TxVa * param: reserved_enote_records - enotes for the proof * param: jamtis_spend_pubkey - K_s * param: sp_spend_privkey - k_m -* param: k_view_balance - k_vb +* param: s_view_balance - k_vb * outparam: proof_out - proof created */ void make_reserve_proof_v1(const rct::key &message, const std::vector &reserved_enote_records, const rct::key &jamtis_spend_pubkey, const crypto::secret_key &sp_spend_privkey, - const crypto::secret_key &k_view_balance, + const crypto::secret_key &s_view_balance, ReserveProofV1 &proof_out); /** * brief: verify reserve proof diff --git a/src/seraphis_main/tx_builder_types.h b/src/seraphis_main/tx_builder_types.h index 1a416c4182d..ad6ec5c2fb7 100644 --- a/src/seraphis_main/tx_builder_types.h +++ b/src/seraphis_main/tx_builder_types.h @@ -106,7 +106,7 @@ struct SpOutputProposalV1 final /// npbits std::uint8_t num_primary_view_tag_bits; /// enc_a - jamtis::encoded_amount_t encoded_amount; + jamtis::encrypted_amount_t encrypted_amount; /// addr_tag_enc jamtis::encrypted_address_tag_t addr_tag_enc; /// view_tag