From 410a9313dcb8f21c815b0eb1bfff1265033e3863 Mon Sep 17 00:00:00 2001 From: jeffro256 Date: Fri, 9 May 2025 02:14:23 -0500 Subject: [PATCH] carrot_core: better exception handling --- src/carrot_core/destination.cpp | 7 +- src/carrot_core/exceptions.h | 75 ++++++++++++++++ src/carrot_core/hash_functions.cpp | 5 +- src/carrot_core/output_set_finalization.cpp | 94 ++++++++++----------- src/carrot_core/payment_proposal.cpp | 44 +++++----- 5 files changed, 149 insertions(+), 76 deletions(-) create mode 100644 src/carrot_core/exceptions.h diff --git a/src/carrot_core/destination.cpp b/src/carrot_core/destination.cpp index 87df93f0f..051f617ea 100644 --- a/src/carrot_core/destination.cpp +++ b/src/carrot_core/destination.cpp @@ -31,6 +31,7 @@ //local headers #include "address_utils.h" +#include "exceptions.h" #include "misc_log_ex.h" #include "ringct/rctOps.h" @@ -39,7 +40,7 @@ //standard headers #undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "carrot" +#define MONERO_DEFAULT_LOG_CATEGORY "carrot.dest" namespace carrot { @@ -71,8 +72,8 @@ void make_carrot_subaddress_v1(const crypto::public_key &account_spend_pubkey, const std::uint32_t j_minor, CarrotDestinationV1 &destination_out) { - CHECK_AND_ASSERT_THROW_MES(j_major != 0 || j_minor, - "make carrot subaddress v1: j cannot be 0 for a subaddress, only for main addresses"); + CARROT_CHECK_AND_THROW(j_major || j_minor, + bad_address_type, "j cannot be 0 for a subaddress, only for main addresses"); // s^j_gen = H_32[s_ga](j_major, j_minor) crypto::secret_key address_index_generator; diff --git a/src/carrot_core/exceptions.h b/src/carrot_core/exceptions.h new file mode 100644 index 000000000..7810af06d --- /dev/null +++ b/src/carrot_core/exceptions.h @@ -0,0 +1,75 @@ +// Copyright (c) 2025, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file Exceptions thrown by Carrot + +#pragma once + +//local headers + +//third party headers + +//standard headers +#include + +//forward declarations + +namespace carrot +{ +#define CARROT_DEFINE_SIMPLE_ERROR_TYPE(e, b) class e: b { using b::b; }; + +class carrot_logic_error: std::logic_error { using std::logic_error::logic_error; }; + +CARROT_DEFINE_SIMPLE_ERROR_TYPE(bad_address_type, carrot_logic_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(component_out_of_order, carrot_logic_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(invalid_point, carrot_logic_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(missing_components, carrot_logic_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(missing_randomness, carrot_logic_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(too_few_inputs, carrot_logic_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(too_few_outputs, carrot_logic_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(too_many_outputs, carrot_logic_error) + +class carrot_runtime_error: std::runtime_error { using std::runtime_error::runtime_error; }; + +CARROT_DEFINE_SIMPLE_ERROR_TYPE(crypto_function_failed, carrot_runtime_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(not_enough_money, carrot_runtime_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(not_enough_usable_money, carrot_runtime_error) +CARROT_DEFINE_SIMPLE_ERROR_TYPE(unexpected_scan_failure, carrot_runtime_error) + +/// one needs to include misc_log_ex.h to use the following macros +#define CARROT_THROW(errtype, message) { \ + std::stringstream ss; \ + ss << message; \ + const std::string msg_str = ss.str(); \ + LOG_ERROR(msg_str); \ + throw errtype(msg_str); \ + } +#define CARROT_CHECK_AND_THROW(expr, errtype, message) if (!(expr)) { CARROT_THROW(errtype, message) } + +#undef CARROT_DEFINE_SIMPLE_ERROR_TYPE +} //namespace carrot diff --git a/src/carrot_core/hash_functions.cpp b/src/carrot_core/hash_functions.cpp index 8eca353d1..0515fd5e2 100644 --- a/src/carrot_core/hash_functions.cpp +++ b/src/carrot_core/hash_functions.cpp @@ -35,6 +35,7 @@ extern "C" #include "crypto/crypto-ops.h" } #include "crypto/blake2b.h" +#include "exceptions.h" #include "misc_log_ex.h" //third party headers @@ -56,13 +57,13 @@ static void hash_base(const void *derivation_key, //32 bytes void *hash_out, const std::size_t out_length) { - CHECK_AND_ASSERT_THROW_MES(blake2b(hash_out, + CARROT_CHECK_AND_THROW(blake2b(hash_out, out_length, data, data_length, derivation_key, derivation_key ? 32 : 0) == 0, - "carrot hash base: blake2b failed."); + crypto_function_failed, "carrot hash base: blake2b failed"); } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- diff --git a/src/carrot_core/output_set_finalization.cpp b/src/carrot_core/output_set_finalization.cpp index 633e4d705..4403e43c4 100644 --- a/src/carrot_core/output_set_finalization.cpp +++ b/src/carrot_core/output_set_finalization.cpp @@ -32,6 +32,7 @@ //local headers #include "common/container_helpers.h" #include "enote_utils.h" +#include "exceptions.h" #include "misc_log_ex.h" #include "ringct/rctOps.h" @@ -41,7 +42,7 @@ #include #undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "carrot" +#define MONERO_DEFAULT_LOG_CATEGORY "carrot.osf" namespace carrot { @@ -62,7 +63,7 @@ std::optional get_additional_output_type(const size_t num_ const bool already_completed = num_outputs >= 2 && num_selfsend >= 1 && !need_change_output; if (num_outputs == 0) { - ASSERT_MES_AND_THROW("get additional output type: set contains 0 outputs"); + CARROT_THROW(too_few_outputs, "set contains 0 outputs"); } else if (already_completed) { @@ -96,8 +97,7 @@ std::optional get_additional_output_type(const size_t num_ } else // num_outputs >= CARROT_MAX_TX_OUTPUTS { - ASSERT_MES_AND_THROW("get additional output type: " - "set needs finalization but already contains too many outputs"); + CARROT_THROW(too_many_outputs, "set needs finalization but already contains too many outputs"); } } //------------------------------------------------------------------------------------------------------------------- @@ -149,7 +149,7 @@ tools::optional_variant &normal_payment_proposals, @@ -170,33 +170,30 @@ void get_output_enote_proposals(const std::vector &norm // assert payment proposals numbers const size_t num_selfsend_proposals = selfsend_payment_proposals.size(); const size_t num_proposals = normal_payment_proposals.size() + num_selfsend_proposals; - CHECK_AND_ASSERT_THROW_MES(num_proposals >= CARROT_MIN_TX_OUTPUTS, - "get output enote proposals: too few payment proposals"); - CHECK_AND_ASSERT_THROW_MES(num_proposals <= CARROT_MAX_TX_OUTPUTS, - "get output enote proposals: too many payment proposals"); - CHECK_AND_ASSERT_THROW_MES(num_selfsend_proposals, - "get output enote proposals: no selfsend payment proposal"); + CARROT_CHECK_AND_THROW(num_proposals >= CARROT_MIN_TX_OUTPUTS, too_few_outputs, "too few payment proposals"); + CARROT_CHECK_AND_THROW(num_proposals <= CARROT_MAX_TX_OUTPUTS, too_many_outputs, "too many payment proposals"); + CARROT_CHECK_AND_THROW(num_selfsend_proposals, too_few_outputs, "no selfsend payment proposal"); // assert there is a max of 1 integrated address payment proposals size_t num_integrated = 0; for (const CarrotPaymentProposalV1 &normal_payment_proposal : normal_payment_proposals) if (normal_payment_proposal.destination.payment_id != null_payment_id) ++num_integrated; - CHECK_AND_ASSERT_THROW_MES(num_integrated <= 1, - "get output enote proposals: only one integrated address is allowed per tx output set"); + CARROT_CHECK_AND_THROW(num_integrated <= 1, + bad_address_type, "only one integrated address is allowed per tx output set"); // assert anchor_norm != 0 for payments for (const CarrotPaymentProposalV1 &normal_payment_proposal : normal_payment_proposals) - CHECK_AND_ASSERT_THROW_MES(normal_payment_proposal.randomness != janus_anchor_t{}, - "get output enote proposals: normal payment proposal has unset anchor_norm AKA randomness"); + CARROT_CHECK_AND_THROW(normal_payment_proposal.randomness != janus_anchor_t{}, + missing_randomness, "normal payment proposal has unset anchor_norm AKA randomness"); // assert uniqueness of randomness for each payment memcmp_set randomnesses; for (const CarrotPaymentProposalV1 &normal_payment_proposal : normal_payment_proposals) randomnesses.insert(normal_payment_proposal.randomness); const bool has_unique_randomness = randomnesses.size() == normal_payment_proposals.size(); - CHECK_AND_ASSERT_THROW_MES(has_unique_randomness, - "get output enote proposals: normal payment proposals contain duplicate anchor_norm AKA randomness"); + CARROT_CHECK_AND_THROW(has_unique_randomness, + missing_randomness, "normal payment proposals contain duplicate anchor_norm AKA randomness"); // for each output: (enote proposal , is ss?, payment idx ) std::vector>> sortable_data; @@ -230,8 +227,8 @@ void get_output_enote_proposals(const std::vector &norm // in the case that there is no required pid_enc, set it to the provided dummy if (0 == num_integrated) { - CHECK_AND_ASSERT_THROW_MES(dummy_encrypted_payment_id, - "get output enote proposals: missing encrypted payment ID: no integrated address nor provided dummy"); + CARROT_CHECK_AND_THROW(dummy_encrypted_payment_id, + missing_components, "missing encrypted payment ID: no integrated address nor provided dummy"); encrypted_payment_id_out = *dummy_encrypted_payment_id; } @@ -268,8 +265,7 @@ void get_output_enote_proposals(const std::vector &norm } else // neither k_v nor s_vb device passed { - ASSERT_MES_AND_THROW( - "get output enote proposals: neither a view-balance nor view-incoming device was provided"); + CARROT_THROW(std::invalid_argument, "neither a view-balance nor view-incoming device was provided"); } } @@ -296,38 +292,38 @@ void get_output_enote_proposals(const std::vector &norm const bool trivial_enote_ephemeral_pubkey = memcmp(p.enote.enote_ephemeral_pubkey.data, mx25519_pubkey{}.data, sizeof(mx25519_pubkey)) == 0; - CHECK_AND_ASSERT_THROW_MES(!trivial_enote_ephemeral_pubkey, - "get output enote proposals: this set contains enote ephemeral pubkeys with x=0"); + CARROT_CHECK_AND_THROW(!trivial_enote_ephemeral_pubkey, missing_randomness, + "this set contains enote ephemeral pubkeys with x=0"); ephemeral_pubkeys.insert(p.enote.enote_ephemeral_pubkey); } const bool has_unique_ephemeral_pubkeys = ephemeral_pubkeys.size() == output_enote_proposals_out.size(); - CHECK_AND_ASSERT_THROW_MES(!(num_proposals == 2 && has_unique_ephemeral_pubkeys), - "get output enote proposals: a 2-out set needs to share an ephemeral pubkey, but this 2-out set doesn't"); - CHECK_AND_ASSERT_THROW_MES(!(num_proposals != 2 && !has_unique_ephemeral_pubkeys), - "get output enote proposals: this >2-out set contains duplicate enote ephemeral pubkeys"); + CARROT_CHECK_AND_THROW(!(num_proposals == 2 && has_unique_ephemeral_pubkeys), + component_out_of_order, "this 2-out set needs to share their ephemeral pubkey"); + CARROT_CHECK_AND_THROW(!(num_proposals != 2 && !has_unique_ephemeral_pubkeys), + missing_randomness, "this >2-out set contains duplicate enote ephemeral pubkeys"); // assert uniqueness of K_o - CHECK_AND_ASSERT_THROW_MES(tools::is_sorted_and_unique(sortable_data, sort_output_enote_proposal), - "get output enote proposals: this set contains duplicate onetime addresses"); + CARROT_CHECK_AND_THROW(tools::is_sorted_and_unique(sortable_data, sort_output_enote_proposal), + component_out_of_order, "this set contains duplicate onetime addresses"); // assert all K_o lie in prime order subgroup for (const RCTOutputEnoteProposal &output_enote_proposal : output_enote_proposals_out) { - CHECK_AND_ASSERT_THROW_MES(rct::isInMainSubgroup(rct::pk2rct(output_enote_proposal.enote.onetime_address)), - "get output enote proposals: this set contains an invalid onetime address"); + CARROT_CHECK_AND_THROW(rct::isInMainSubgroup(rct::pk2rct(output_enote_proposal.enote.onetime_address)), + invalid_point, "this set contains an invalid onetime address"); } // assert unique and non-trivial k_a memcmp_set amount_blinding_factors; for (const RCTOutputEnoteProposal &output_enote_proposal : output_enote_proposals_out) { - CHECK_AND_ASSERT_THROW_MES(output_enote_proposal.amount_blinding_factor != crypto::null_skey, - "get output enote proposals: this set contains a trivial amount blinding factor"); + CARROT_CHECK_AND_THROW(output_enote_proposal.amount_blinding_factor != crypto::null_skey, + missing_randomness, "this set contains a trivial amount blinding factor"); amount_blinding_factors.insert(output_enote_proposal.amount_blinding_factor); } - CHECK_AND_ASSERT_THROW_MES(amount_blinding_factors.size() == num_proposals, - "get output enote proposals: this set contains duplicate amount blinding factors"); + CARROT_CHECK_AND_THROW(amount_blinding_factors.size() == num_proposals, missing_randomness, + "this set contains duplicate amount blinding factors"); } //------------------------------------------------------------------------------------------------------------------- void get_coinbase_output_enotes(const std::vector &normal_payment_proposals, @@ -343,22 +339,22 @@ void get_coinbase_output_enotes(const std::vector &norm for (const CarrotPaymentProposalV1 &normal_payment_proposal : normal_payment_proposals) { const CarrotDestinationV1 &destination = normal_payment_proposal.destination; - CHECK_AND_ASSERT_THROW_MES(destination.payment_id == null_payment_id && !destination.is_subaddress, - "get coinbase output enotes: no integrated addresses or subaddresses allowed"); + CARROT_CHECK_AND_THROW(destination.payment_id == null_payment_id && !destination.is_subaddress, + bad_address_type, "get coinbase output enotes: no integrated addresses or subaddresses allowed"); } // assert anchor_norm != 0 for payments for (const CarrotPaymentProposalV1 &normal_payment_proposal : normal_payment_proposals) - CHECK_AND_ASSERT_THROW_MES(normal_payment_proposal.randomness != janus_anchor_t{}, - "get coinbase output enotes: normal payment proposal has unset anchor_norm AKA randomness"); + CARROT_CHECK_AND_THROW(normal_payment_proposal.randomness != janus_anchor_t{}, + missing_randomness, "normal payment proposal has unset anchor_norm AKA randomness"); // assert uniqueness of randomness for each payment memcmp_set randomnesses; for (const CarrotPaymentProposalV1 &normal_payment_proposal : normal_payment_proposals) randomnesses.insert(normal_payment_proposal.randomness); const bool has_unique_randomness = randomnesses.size() == normal_payment_proposals.size(); - CHECK_AND_ASSERT_THROW_MES(has_unique_randomness, - "get coinbase output enotes: normal payment proposals contain duplicate anchor_norm AKA randomness"); + CARROT_CHECK_AND_THROW(has_unique_randomness, + missing_randomness, "normal payment proposals contain duplicate anchor_norm AKA randomness"); // construct normal enotes output_coinbase_enotes_out.reserve(num_proposals); @@ -376,13 +372,13 @@ void get_coinbase_output_enotes(const std::vector &norm const bool trivial_enote_ephemeral_pubkey = memcmp(enote.enote_ephemeral_pubkey.data, mx25519_pubkey{}.data, sizeof(mx25519_pubkey)) == 0; - CHECK_AND_ASSERT_THROW_MES(!trivial_enote_ephemeral_pubkey, - "get coinbase output enotes: this set contains enote ephemeral pubkeys with x=0"); + CARROT_CHECK_AND_THROW(!trivial_enote_ephemeral_pubkey, + missing_randomness, "this set contains enote ephemeral pubkeys with x=0"); ephemeral_pubkeys.insert(enote.enote_ephemeral_pubkey); } const bool has_unique_ephemeral_pubkeys = ephemeral_pubkeys.size() == output_coinbase_enotes_out.size(); - CHECK_AND_ASSERT_THROW_MES(has_unique_ephemeral_pubkeys, - "get coinbase output enotes: a coinbase enote set needs unique ephemeral pubkeys, but this set doesn't"); + CARROT_CHECK_AND_THROW(has_unique_ephemeral_pubkeys, + missing_randomness, "a coinbase enote set needs unique ephemeral pubkeys, but this set doesn't"); // sort enotes by K_o const auto sort_output_enote_proposal = [](const CarrotCoinbaseEnoteV1 &a, const CarrotCoinbaseEnoteV1 &b) @@ -390,14 +386,14 @@ void get_coinbase_output_enotes(const std::vector &norm std::sort(output_coinbase_enotes_out.begin(), output_coinbase_enotes_out.end(), sort_output_enote_proposal); // assert uniqueness of K_o - CHECK_AND_ASSERT_THROW_MES(tools::is_sorted_and_unique(output_coinbase_enotes_out, sort_output_enote_proposal), - "get coinbase output enotes: this set contains duplicate onetime addresses"); + CARROT_CHECK_AND_THROW(tools::is_sorted_and_unique(output_coinbase_enotes_out, sort_output_enote_proposal), + component_out_of_order, "this set contains duplicate onetime addresses"); // assert all K_o lie in prime order subgroup for (const CarrotCoinbaseEnoteV1 &output_enote : output_coinbase_enotes_out) { - CHECK_AND_ASSERT_THROW_MES(rct::isInMainSubgroup(rct::pk2rct(output_enote.onetime_address)), - "get coinbase output enotes: this set contains an invalid onetime address"); + CARROT_CHECK_AND_THROW(rct::isInMainSubgroup(rct::pk2rct(output_enote.onetime_address)), + invalid_point, "this set contains an invalid onetime address"); } } //------------------------------------------------------------------------------------------------------------------- diff --git a/src/carrot_core/payment_proposal.cpp b/src/carrot_core/payment_proposal.cpp index 16d1730b4..3bc525709 100644 --- a/src/carrot_core/payment_proposal.cpp +++ b/src/carrot_core/payment_proposal.cpp @@ -32,6 +32,7 @@ //local headers #include "int-util.h" #include "enote_utils.h" +#include "exceptions.h" #include "misc_language.h" #include "misc_log_ex.h" #include "ringct/rctOps.h" @@ -42,7 +43,7 @@ #undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "carrot" +#define MONERO_DEFAULT_LOG_CATEGORY "carrot.pp" namespace carrot { @@ -237,12 +238,12 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal, CarrotCoinbaseEnoteV1 &output_enote_out) { // 1. sanity checks - CHECK_AND_ASSERT_THROW_MES(proposal.randomness != null_anchor, - "get coinbase output proposal v1: invalid randomness for janus anchor (zero)."); - CHECK_AND_ASSERT_THROW_MES(!proposal.destination.is_subaddress, - "get coinbase output proposal v1: subaddresses aren't allowed as destinations of coinbase outputs"); - CHECK_AND_ASSERT_THROW_MES(proposal.destination.payment_id == null_payment_id, - "get coinbase output proposal v1: integrated addresses aren't allowed as destinations of coinbase outputs"); + CARROT_CHECK_AND_THROW(proposal.randomness != null_anchor, + missing_randomness, "invalid randomness for janus anchor (zero)."); + CARROT_CHECK_AND_THROW(!proposal.destination.is_subaddress, + bad_address_type, "subaddresses aren't allowed as destinations of coinbase outputs"); + CARROT_CHECK_AND_THROW(proposal.destination.payment_id == null_payment_id, + bad_address_type, "integrated addresses aren't allowed as destinations of coinbase outputs"); // 2. coinbase input context const input_context_t input_context= make_carrot_input_context_coinbase(block_index); @@ -292,8 +293,8 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal, encrypted_payment_id_t &encrypted_payment_id_out) { // 1. sanity checks - CHECK_AND_ASSERT_THROW_MES(proposal.randomness != null_anchor, - "jamtis payment proposal: invalid randomness for janus anchor (zero)."); + CARROT_CHECK_AND_THROW(proposal.randomness != null_anchor, + missing_randomness, "invalid randomness for janus anchor (zero)."); // 2. input context: input_context = "R" || KI_1 const input_context_t input_context = make_carrot_input_context(tx_first_key_image); @@ -340,8 +341,8 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo RCTOutputEnoteProposal &output_enote_out) { // 1. sanity checks - CHECK_AND_ASSERT_THROW_MES(!proposal.internal_message, - "get output proposal special v1: internal messages are only for internal selfsends, not special selfsends"); + CARROT_CHECK_AND_THROW(!proposal.internal_message, + component_out_of_order, "internal messages are only for internal selfsends, not special selfsends"); // 2. input context: input_context = "R" || KI_1 const input_context_t input_context = make_carrot_input_context(tx_first_key_image); @@ -351,18 +352,17 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo const bool mismatched_enote_ephemeral_pubkeys = proposal.enote_ephemeral_pubkey && other_enote_ephemeral_pubkey && memcmp(&*proposal.enote_ephemeral_pubkey, &*other_enote_ephemeral_pubkey, sizeof(mx25519_pubkey)); - CHECK_AND_ASSERT_THROW_MES(!missing_enote_ephemeral_pubkeys, - "get output proposal special v1: no enote ephemeral pubkey provided"); - CHECK_AND_ASSERT_THROW_MES(!mismatched_enote_ephemeral_pubkeys, - "get output proposal special v1: mismatched enote ephemeral pubkeys provided"); + CARROT_CHECK_AND_THROW(!missing_enote_ephemeral_pubkeys, + missing_components, "no enote ephemeral pubkey provided"); + CARROT_CHECK_AND_THROW(!mismatched_enote_ephemeral_pubkeys, + component_out_of_order, "mismatched enote ephemeral pubkeys provided"); const mx25519_pubkey enote_ephemeral_pubkey = proposal.enote_ephemeral_pubkey.value_or( other_enote_ephemeral_pubkey.value_or(mx25519_pubkey{})); // 4. s_sr = k_v D_e mx25519_pubkey s_sender_receiver_unctx; auto ecdh_wiper = auto_wiper(s_sender_receiver_unctx); - CHECK_AND_ASSERT_THROW_MES(k_view_dev.view_key_scalar_mult_x25519(enote_ephemeral_pubkey, - s_sender_receiver_unctx), - "get output proposal special v1: HW device failed to perform ECDH with ephemeral pubkey"); + CARROT_CHECK_AND_THROW(k_view_dev.view_key_scalar_mult_x25519(enote_ephemeral_pubkey, s_sender_receiver_unctx), + crypto_function_failed, "HW device failed to perform ECDH with ephemeral pubkey"); // 5. build the output enote address pieces crypto::hash s_sender_receiver; auto q_wiper = auto_wiper(s_sender_receiver); @@ -418,10 +418,10 @@ void get_output_proposal_internal_v1(const CarrotPaymentProposalSelfSendV1 &prop const bool mismatched_enote_ephemeral_pubkeys = proposal.enote_ephemeral_pubkey && other_enote_ephemeral_pubkey && memcmp(&*proposal.enote_ephemeral_pubkey, &*other_enote_ephemeral_pubkey, sizeof(mx25519_pubkey)); - CHECK_AND_ASSERT_THROW_MES(!missing_enote_ephemeral_pubkeys, - "get output proposal internal v1: no enote ephemeral pubkey provided"); - CHECK_AND_ASSERT_THROW_MES(!mismatched_enote_ephemeral_pubkeys, - "get output proposal internal v1: mismatched enote ephemeral pubkeys provided"); + CARROT_CHECK_AND_THROW(!missing_enote_ephemeral_pubkeys, + missing_components, "no enote ephemeral pubkey provided"); + CARROT_CHECK_AND_THROW(!mismatched_enote_ephemeral_pubkeys, + component_out_of_order, "mismatched enote ephemeral pubkeys provided"); const mx25519_pubkey enote_ephemeral_pubkey = proposal.enote_ephemeral_pubkey.value_or( other_enote_ephemeral_pubkey.value_or(mx25519_pubkey{}));