carrot_core: better exception handling
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 <stdexcept>
|
||||
|
||||
//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
|
||||
@@ -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");
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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 <set>
|
||||
|
||||
#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<AdditionalOutputType> 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<AdditionalOutputType> 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<CarrotPaymentProposalV1, CarrotPaymentProposalSelfSendV1
|
||||
};
|
||||
}
|
||||
|
||||
ASSERT_MES_AND_THROW("get additional output proposal: unrecognized additional output type");
|
||||
CARROT_THROW(std::invalid_argument, "unrecognized additional output type");
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &normal_payment_proposals,
|
||||
@@ -170,33 +170,30 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &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<janus_anchor_t> 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<std::pair<RCTOutputEnoteProposal, std::pair<bool, size_t>>> sortable_data;
|
||||
@@ -230,8 +227,8 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &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<CarrotPaymentProposalV1> &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<CarrotPaymentProposalV1> &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<crypto::secret_key> 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<CarrotPaymentProposalV1> &normal_payment_proposals,
|
||||
@@ -343,22 +339,22 @@ void get_coinbase_output_enotes(const std::vector<CarrotPaymentProposalV1> &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<janus_anchor_t> 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<CarrotPaymentProposalV1> &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<CarrotPaymentProposalV1> &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");
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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{}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user