diff --git a/src/carrot_core/enote_utils.cpp b/src/carrot_core/enote_utils.cpp index e6a7e3d..adcfbc4 100644 --- a/src/carrot_core/enote_utils.cpp +++ b/src/carrot_core/enote_utils.cpp @@ -221,6 +221,26 @@ void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_recei derive_bytes_32(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_pubkey_mask_out); } //------------------------------------------------------------------------------------------------------------------- +void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32], + const input_context_t &input_context, + const view_balance_secret_device *s_view_balance_dev, + const crypto::public_key &onetime_address, + encrypted_return_pubkey_t &return_pubkey_out) +{ + // K_return = k_return G ^ m_return + crypto::secret_key k_return; + crypto::public_key return_pub; + encrypted_return_pubkey_t K_return; + encrypted_return_pubkey_t m_return; + s_view_balance_dev->make_internal_return_privkey(input_context, onetime_address, k_return); + crypto::secret_key_to_public_key(k_return, return_pub); + static_assert(sizeof(K_return.bytes) == sizeof(return_pub.data), "Size mismatch"); + memcpy(K_return.bytes, return_pub.data, sizeof(encrypted_return_pubkey_t)); + make_sparc_return_pubkey_encryption_mask(s_sender_receiver_unctx, input_context, onetime_address, m_return); + return_pubkey_out = K_return ^ m_return; +} +//------------------------------------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------------------------- input_context_t make_carrot_input_context_coinbase(const std::uint64_t block_index) { // input_context = "C" || IntToBytes256(block_index) diff --git a/src/carrot_core/enote_utils.h b/src/carrot_core/enote_utils.h index 324138b..03e6844 100644 --- a/src/carrot_core/enote_utils.h +++ b/src/carrot_core/enote_utils.h @@ -35,6 +35,7 @@ #include "core_types.h" #include "mx25519.h" #include "ringct/rctTypes.h" +#include "device.h" //third party headers @@ -148,6 +149,20 @@ void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_recei const input_context_t &input_context, const crypto::public_key &onetime_address, encrypted_return_pubkey_t &return_pubkey_mask_out); + +/** +* brief: make_sparc_return_pubkey - construct the return pubkey +* param: s_sender_receiver_unctx - s_sr +* param: input_context - input_context +* param: s_view_balance_dev - s_vb +* param: onetime_address - Ko +* outparam: return_pubkey_mask_out - K_return +*/ +void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32], + const input_context_t &input_context, + const view_balance_secret_device *s_view_balance_dev, + const crypto::public_key &onetime_address, + encrypted_return_pubkey_t &return_pubkey_out); /** * brief: make_carrot_input_context_coinbase - input context for a sender-receiver secret (coinbase txs) * input_context = "C" || IntToBytes256(block_index) diff --git a/src/carrot_core/output_set_finalization.cpp b/src/carrot_core/output_set_finalization.cpp index f9a051f..d5ab10b 100644 --- a/src/carrot_core/output_set_finalization.cpp +++ b/src/carrot_core/output_set_finalization.cpp @@ -161,6 +161,7 @@ void get_output_enote_proposals(const std::vector &norm std::vector &output_enote_proposals_out, encrypted_payment_id_t &encrypted_payment_id_out, size_t &change_index_out, + std::unordered_map &normal_payments_indices_out, std::vector> *payment_proposal_order_out) { output_enote_proposals_out.clear(); @@ -203,6 +204,10 @@ void get_output_enote_proposals(const std::vector &norm // D^other_e std::optional other_enote_ephemeral_pubkey; + + // map destinations to output keys to be able to find the indices of these outputs in tx + std::unordered_map output_destinations_to_keys; + // construct normal enotes for (size_t i = 0; i < normal_payment_proposals.size(); ++i) { @@ -212,6 +217,7 @@ void get_output_enote_proposals(const std::vector &norm encrypted_payment_id_t encrypted_payment_id; get_output_proposal_normal_v1(normal_payment_proposals[i], tx_first_key_image, + s_view_balance_dev, output_entry.first, encrypted_payment_id); @@ -223,6 +229,11 @@ void get_output_enote_proposals(const std::vector &norm const bool is_integrated = normal_payment_proposals[i].destination.payment_id != null_payment_id; if (is_integrated) encrypted_payment_id_out = encrypted_payment_id; + + // save the one time key for this destination + output_destinations_to_keys.insert( + {output_entry.first.enote.onetime_address, normal_payment_proposals[i].destination.address_spend_pubkey} + ); } // in the case that there is no required pid_enc, set it to the provided dummy @@ -287,8 +298,13 @@ void get_output_enote_proposals(const std::vector &norm if (sortable_data[i].first.enote.onetime_address == change_address) { change_index_out = i; - break; + continue; } + + const auto spend_key = output_destinations_to_keys[sortable_data[i].first.enote.onetime_address]; + normal_payments_indices_out.insert( + {spend_key, i} + ); } // collect output_enote_proposals_out and payment_proposal_order_out diff --git a/src/carrot_core/output_set_finalization.h b/src/carrot_core/output_set_finalization.h index d9bb54d..42b5f84 100644 --- a/src/carrot_core/output_set_finalization.h +++ b/src/carrot_core/output_set_finalization.h @@ -111,6 +111,7 @@ void get_output_enote_proposals(const std::vector &norm std::vector &output_enote_proposals_out, encrypted_payment_id_t &encrypted_payment_id_out, size_t &change_index_out, + std::unordered_map &normal_payments_indices_out, std::vector> *payment_proposal_order_out = nullptr); /** * brief: get_coinbase_output_enotes - convert a *finalized* set of payment proposals into coinbase output enotes diff --git a/src/carrot_core/payment_proposal.cpp b/src/carrot_core/payment_proposal.cpp index 3f34a8c..3cba698 100644 --- a/src/carrot_core/payment_proposal.cpp +++ b/src/carrot_core/payment_proposal.cpp @@ -170,6 +170,7 @@ static void get_external_output_proposal_parts(const mx25519_pubkey &s_sender_re const CarrotEnoteType enote_type, const mx25519_pubkey &enote_ephemeral_pubkey, const input_context_t &input_context, + const view_balance_secret_device *s_view_balance_dev, const bool coinbase_amount_commitment, crypto::hash &s_sender_receiver_out, crypto::secret_key &amount_blinding_factor_out, @@ -177,7 +178,8 @@ static void get_external_output_proposal_parts(const mx25519_pubkey &s_sender_re crypto::public_key &onetime_address_out, encrypted_amount_t &encrypted_amount_out, encrypted_payment_id_t &encrypted_payment_id_out, - view_tag_t &view_tag_out) + view_tag_t &view_tag_out, + encrypted_return_pubkey_t return_pubkey_out) { // 1. s^ctx_sr = H_32(s_sr, D_e, input_context) make_carrot_sender_receiver_secret(s_sender_receiver_unctx.data, @@ -202,6 +204,14 @@ static void get_external_output_proposal_parts(const mx25519_pubkey &s_sender_re // 3. vt = H_3(s_sr || input_context || Ko) make_carrot_view_tag(s_sender_receiver_unctx.data, input_context, onetime_address_out, view_tag_out); + + // 4. construct the return pubkey + if (s_view_balance_dev != nullptr) + make_sparc_return_pubkey(s_sender_receiver_unctx.data, + input_context, + s_view_balance_dev, + onetime_address_out, + return_pubkey_out); } //------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------- @@ -257,6 +267,7 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal, // 4. build the output enote address pieces crypto::hash s_sender_receiver; auto q_wiper = auto_wiper(s_sender_receiver); + encrypted_return_pubkey_t return_pubkey_out; crypto::secret_key dummy_amount_blinding_factor; rct::key dummy_amount_commitment; encrypted_amount_t dummy_encrypted_amount; @@ -268,6 +279,7 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal, CarrotEnoteType::PAYMENT, output_enote_out.enote_ephemeral_pubkey, input_context, + nullptr, // s_view_balance_dev true, // coinbase_amount_commitment s_sender_receiver, dummy_amount_blinding_factor, @@ -275,8 +287,9 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal, output_enote_out.onetime_address, dummy_encrypted_amount, dummy_encrypted_payment_id, - output_enote_out.view_tag); - + output_enote_out.view_tag, + return_pubkey_out); + // 5. anchor_enc = anchor XOR m_anchor output_enote_out.anchor_enc = encrypt_carrot_anchor(proposal.randomness, s_sender_receiver, @@ -290,6 +303,7 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal, //------------------------------------------------------------------------------------------------------------------- void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal, const crypto::key_image &tx_first_key_image, + const view_balance_secret_device *s_view_balance_dev, RCTOutputEnoteProposal &output_enote_out, encrypted_payment_id_t &encrypted_payment_id_out) { @@ -309,6 +323,7 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal, // 4. build the output enote address pieces crypto::hash s_sender_receiver; auto q_wiper = auto_wiper(s_sender_receiver); + encrypted_return_pubkey_t return_pubkey; get_external_output_proposal_parts(s_sender_receiver_unctx, proposal.destination.address_spend_pubkey, proposal.destination.payment_id, @@ -316,6 +331,7 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal, CarrotEnoteType::PAYMENT, output_enote_out.enote.enote_ephemeral_pubkey, input_context, + s_view_balance_dev, false, // coinbase_amount_commitment s_sender_receiver, output_enote_out.amount_blinding_factor, @@ -323,17 +339,19 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal, output_enote_out.enote.onetime_address, output_enote_out.enote.amount_enc, encrypted_payment_id_out, - output_enote_out.enote.view_tag); - + output_enote_out.enote.view_tag, + return_pubkey); + // 5. anchor_enc = anchor XOR m_anchor output_enote_out.enote.anchor_enc = encrypt_carrot_anchor(proposal.randomness, s_sender_receiver, output_enote_out.enote.onetime_address); // 6. save the amount and first key image - output_enote_out.amount = proposal.amount; - output_enote_out.enote.asset_type = proposal.asset_type; - output_enote_out.enote.tx_first_key_image = tx_first_key_image; + output_enote_out.amount = proposal.amount; + output_enote_out.enote.asset_type = proposal.asset_type; + output_enote_out.enote.tx_first_key_image = tx_first_key_image; + output_enote_out.enote.return_enc = return_pubkey; } //------------------------------------------------------------------------------------------------------------------- void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &proposal, @@ -368,6 +386,7 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo // 5. build the output enote address pieces crypto::hash s_sender_receiver; auto q_wiper = auto_wiper(s_sender_receiver); + encrypted_return_pubkey_t return_pubkey_out; encrypted_payment_id_t dummy_encrypted_payment_id; get_external_output_proposal_parts(s_sender_receiver_unctx, proposal.destination_address_spend_pubkey, @@ -376,6 +395,7 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo proposal.enote_type, enote_ephemeral_pubkey, input_context, + nullptr, false, // coinbase_amount_commitment s_sender_receiver, output_enote_out.amount_blinding_factor, @@ -383,7 +403,8 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo output_enote_out.enote.onetime_address, output_enote_out.enote.amount_enc, dummy_encrypted_payment_id, - output_enote_out.enote.view_tag); + output_enote_out.enote.view_tag, + return_pubkey_out); // 6. make special janus anchor: anchor_sp = H_16(D_e, input_context, Ko, k_v) janus_anchor_t janus_anchor_special; @@ -425,6 +446,7 @@ void get_output_proposal_return_v1(const CarrotPaymentProposalV1 &proposal, // 4. build the output enote address pieces crypto::hash s_sender_receiver; auto q_wiper = auto_wiper(s_sender_receiver); + encrypted_return_pubkey_t return_pubkey_out; // HERE BE DRAGONS!!! // SRCG: the following call needs the "destination" parameter adjusted for return_payment get_external_output_proposal_parts(s_sender_receiver_unctx, @@ -434,6 +456,7 @@ void get_output_proposal_return_v1(const CarrotPaymentProposalV1 &proposal, CarrotEnoteType::PAYMENT, output_enote_out.enote.enote_ephemeral_pubkey, input_context, + nullptr, false, s_sender_receiver, output_enote_out.amount_blinding_factor, @@ -441,7 +464,8 @@ void get_output_proposal_return_v1(const CarrotPaymentProposalV1 &proposal, output_enote_out.enote.onetime_address, output_enote_out.enote.amount_enc, encrypted_payment_id_out, - output_enote_out.enote.view_tag); + output_enote_out.enote.view_tag, + return_pubkey_out); // 5. Override the values that change because of the enote onetime address (K_o) changing // i.e. {K_o, vt, m_a, a_enc, m_anchor, anchor_enc, m_pid, pid_enc} diff --git a/src/carrot_core/payment_proposal.h b/src/carrot_core/payment_proposal.h index c461032..db5927c 100644 --- a/src/carrot_core/payment_proposal.h +++ b/src/carrot_core/payment_proposal.h @@ -133,6 +133,7 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal, */ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal, const crypto::key_image &tx_first_key_image, + const view_balance_secret_device *s_view_balance_dev, RCTOutputEnoteProposal &output_enote_out, encrypted_payment_id_t &encrypted_payment_id_out); /** diff --git a/src/carrot_impl/format_utils.cpp b/src/carrot_impl/format_utils.cpp index 9acac37..cfe53bf 100644 --- a/src/carrot_impl/format_utils.cpp +++ b/src/carrot_impl/format_utils.cpp @@ -197,18 +197,27 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector &key_images, const std::vector &sources, const rct::xmr_amount fee, + const cryptonote::transaction_type tx_type, + const size_t change_index, + const std::vector change_masks, const encrypted_payment_id_t encrypted_payment_id) { const size_t nins = key_images.size(); const size_t nouts = enotes.size(); CHECK_AND_ASSERT_THROW_MES(nins == sources.size(), "invalid inputs/sources size"); + CHECK_AND_ASSERT_THROW_MES(change_masks.size() == nouts - 1, "invalid change masks size. Expected: " << nouts - 1 << " got: " << change_masks.size()); cryptonote::transaction tx; tx.pruned = true; tx.version = TRANSACTION_VERSION_N_OUTS; tx.unlock_time = 0; + tx.source_asset_type = "SAL1"; + tx.destination_asset_type = "SAL1"; + tx.type = tx_type; + tx.return_address_change_mask.assign(change_masks.begin(), change_masks.end()); tx.vin.reserve(nins); tx.vout.reserve(nouts); + tx.return_address_list.reserve(change_masks.size()); tx.extra.reserve(MAX_TX_EXTRA_SIZE); tx.rct_signatures.type = carrot_v1_rct_type; tx.rct_signatures.txnFee = fee; @@ -233,6 +242,7 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector &key_images, const std::vector &sources, const rct::xmr_amount fee, + const cryptonote::transaction_type tx_type, + const size_t change_index, + const std::vector change_masks, const encrypted_payment_id_t encrypted_payment_id); /** * brief: try_load_carrot_enote_from_transaction_v1 - load one non-coinbase Carrot enote from a cryptonote::transaction diff --git a/src/carrot_impl/tx_builder_outputs.cpp b/src/carrot_impl/tx_builder_outputs.cpp index e4b9589..b22460d 100644 --- a/src/carrot_impl/tx_builder_outputs.cpp +++ b/src/carrot_impl/tx_builder_outputs.cpp @@ -60,6 +60,7 @@ void get_output_enote_proposals_from_proposal_v1(const CarrotTransactionProposal // derive enote proposals size_t change_index; + std::unordered_map normal_payments_indices; get_output_enote_proposals(tx_proposal.normal_payment_proposals, selfsend_payment_proposal_cores, tx_proposal.dummy_encrypted_payment_id, @@ -69,6 +70,7 @@ void get_output_enote_proposals_from_proposal_v1(const CarrotTransactionProposal output_enote_proposals_out, encrypted_payment_id_out, change_index, + normal_payments_indices, payment_proposal_order_out); } //------------------------------------------------------------------------------------------------------------------- @@ -123,6 +125,9 @@ void make_pruned_transaction_from_proposal_v1(const CarrotTransactionProposalV1 tx_proposal.key_images_sorted, tx_proposal.sources, tx_proposal.fee, + cryptonote::transaction_type::TRANSFER, + 0, // change_index + {}, // change_masks encrypted_payment_id); // add extra payload and sort diff --git a/src/wallet/tx_builder.cpp b/src/wallet/tx_builder.cpp index 7a65810..c24a687 100644 --- a/src/wallet/tx_builder.cpp +++ b/src/wallet/tx_builder.cpp @@ -47,6 +47,7 @@ #include "ringct/bulletproofs_plus.h" #include "wallet/scanning_tools.cpp" #include "common/container_helpers.h" +#include "carrot_core/payment_proposal.cpp" //third party headers @@ -872,6 +873,53 @@ bool get_address_openings_x_y( return true; } //------------------------------------------------------------------------------------------------------------------- +void encrypt_change_index( + const std::vector &proposals, + const crypto::key_image &tx_first_key_image, + const size_t change_index, + const std::unordered_map &normal_payments_indices, + std::vector &change_masks_out +) { + // 2. input context: input_context = "R" || KI_1 + const carrot::input_context_t input_context = carrot::make_carrot_input_context(tx_first_key_image); + + // 3. make D_e and do external ECDH + for (const auto &p: proposals) { + // get shared secret + mx25519_pubkey s_sender_receiver_unctx; + mx25519_pubkey eph_pubkey; + carrot::get_normal_proposal_ecdh_parts( + p, + input_context, + eph_pubkey, + s_sender_receiver_unctx + ); + + // derive a scalar from the shared secret + crypto::secret_key output_index_key; + crypto::key_derivation output_index_derivation; + memcpy(output_index_derivation.data, s_sender_receiver_unctx.data, sizeof(output_index_derivation.data)); + crypto::derivation_to_scalar( + output_index_derivation, + normal_payments_indices.at(p.destination.address_spend_pubkey), + output_index_key + ); + + // Calculate the encrypted_change_index data for this output + struct { + char domain_separator[8]; + crypto::secret_key output_index_key; + } eci_buf; + std::memset(eci_buf.domain_separator, 0x0, sizeof(eci_buf.domain_separator)); + std::strncpy(eci_buf.domain_separator, "CHG_IDX", 8); + eci_buf.output_index_key = output_index_key; + crypto::secret_key eci_out; + keccak((uint8_t *)&eci_buf, sizeof(eci_buf), (uint8_t*)&eci_out, sizeof(eci_out)); + uint8_t eci_data = change_index ^ eci_out.data[0]; + change_masks_out.push_back(eci_data); + } +} +//------------------------------------------------------------------------------------------------------------------- cryptonote::transaction finalize_all_proofs_from_transfer_details( const carrot::CarrotTransactionProposalV1 &tx_proposal, const cryptonote::transaction_type tx_type, @@ -908,6 +956,7 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details( std::vector output_enote_proposals; carrot::encrypted_payment_id_t encrypted_payment_id; size_t change_index; + std::unordered_map normal_payments_indices; carrot::get_output_enote_proposals(tx_proposal.normal_payment_proposals, selfsend_payment_proposal_cores, tx_proposal.dummy_encrypted_payment_id, @@ -917,6 +966,7 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details( output_enote_proposals, encrypted_payment_id, change_index, + normal_payments_indices, nullptr); CHECK_AND_ASSERT_THROW_MES(output_enote_proposals.size() == n_outputs, "finalize_all_proofs_from_transfer_details: unexpected number of output enote proposals"); @@ -940,15 +990,24 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details( for (size_t i = 0; i < enotes.size(); ++i) enotes[i] = output_enote_proposals.at(i).enote; + // encrypt change index per output + std::vector change_masks; + encrypt_change_index( + tx_proposal.normal_payment_proposals, + tx_proposal.key_images_sorted.at(0), + change_index, + normal_payments_indices, + change_masks); + // serialize transaction cryptonote::transaction tx = carrot::store_carrot_to_transaction_v1(enotes, tx_proposal.key_images_sorted, tx_proposal.sources, tx_proposal.fee, + tx_type, + change_index, + change_masks, encrypted_payment_id); - tx.source_asset_type = "SAL1"; - tx.destination_asset_type = "SAL1"; - tx.type = tx_type; // aliases hw::device &hwdev = acc_keys.get_device(); @@ -1068,9 +1127,6 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details( } } - // fee - uint64_t fee = amount_in - amount_out - tx.amount_burnt; - // bpp tx.rct_signatures.p.bulletproofs_plus.push_back( rct::bulletproof_plus_PROVE(outamounts, output_amount_blinding_factors) @@ -1090,7 +1146,7 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details( destination_asset_types, inamounts, outamounts, - fee, + tx_proposal.fee, mixRing, index, outSk, diff --git a/tests/performance_tests/view_scan.h b/tests/performance_tests/view_scan.h index d5bf279..addb99a 100644 --- a/tests/performance_tests/view_scan.h +++ b/tests/performance_tests/view_scan.h @@ -222,6 +222,7 @@ public: carrot::RCTOutputEnoteProposal output_proposal; carrot::get_output_proposal_normal_v1(payment_proposal, {}, + nullptr, output_proposal, m_encrypted_payment_id); m_enote = output_proposal.enote; diff --git a/tests/unit_tests/carrot_core.cpp b/tests/unit_tests/carrot_core.cpp index 0193043..68054e3 100644 --- a/tests/unit_tests/carrot_core.cpp +++ b/tests/unit_tests/carrot_core.cpp @@ -115,6 +115,7 @@ TEST(carrot_core, main_address_normal_scan_completeness) encrypted_payment_id_t encrypted_payment_id; get_output_proposal_normal_v1(proposal, tx_first_key_image, + nullptr, // s_view_balance_dev enote_proposal, encrypted_payment_id); @@ -185,6 +186,7 @@ TEST(carrot_core, subaddress_normal_scan_completeness) encrypted_payment_id_t encrypted_payment_id; get_output_proposal_normal_v1(proposal, tx_first_key_image, + nullptr, // s_view_balance_dev enote_proposal, encrypted_payment_id); @@ -252,6 +254,7 @@ TEST(carrot_core, integrated_address_normal_scan_completeness) encrypted_payment_id_t encrypted_payment_id; get_output_proposal_normal_v1(proposal, tx_first_key_image, + nullptr, // s_view_balance_dev enote_proposal, encrypted_payment_id); @@ -711,6 +714,7 @@ static void subtest_2out_transfer_get_output_enote_proposals_completeness(const std::vector enote_proposals; encrypted_payment_id_t encrypted_payment_id; size_t change_index; + std::unordered_map normal_payments_indices; get_output_enote_proposals({bob_payment_proposal}, {alice_payment_proposal}, dummy_encrypted_pid, @@ -719,7 +723,8 @@ static void subtest_2out_transfer_get_output_enote_proposals_completeness(const tx_first_key_image, enote_proposals, encrypted_payment_id, - change_index); + change_index, + normal_payments_indices); ASSERT_EQ(2, enote_proposals.size()); // 2-out tx diff --git a/tests/unit_tests/carrot_fcmp.cpp b/tests/unit_tests/carrot_fcmp.cpp index c8f264d..341aeb2 100644 --- a/tests/unit_tests/carrot_fcmp.cpp +++ b/tests/unit_tests/carrot_fcmp.cpp @@ -375,6 +375,7 @@ TEST(carrot_fcmp, receive_scan_spend_and_verify_serialized_carrot_tx) std::vector output_enote_proposals; encrypted_payment_id_t encrypted_payment_id; size_t change_index; + std::unordered_map normal_payments_indices; get_output_enote_proposals(tx_proposal.normal_payment_proposals, selfsend_payment_proposal_cores, tx_proposal.dummy_encrypted_payment_id, @@ -384,7 +385,8 @@ TEST(carrot_fcmp, receive_scan_spend_and_verify_serialized_carrot_tx) tx_proposal.key_images_sorted.at(0), output_enote_proposals, encrypted_payment_id, - change_index); + change_index, + normal_payments_indices); // Collect balance info and enotes std::vector input_onetime_addresses; @@ -413,6 +415,8 @@ TEST(carrot_fcmp, receive_scan_spend_and_verify_serialized_carrot_tx) tx_proposal.key_images_sorted, tx_proposal.sources, tx_proposal.fee, + 0, // change_index + {}, // change_masks encrypted_payment_id); ASSERT_EQ(2, tx.version); diff --git a/tests/unit_tests/carrot_impl.cpp b/tests/unit_tests/carrot_impl.cpp index 5bbddf9..ac969e6 100644 --- a/tests/unit_tests/carrot_impl.cpp +++ b/tests/unit_tests/carrot_impl.cpp @@ -205,6 +205,7 @@ static void subtest_multi_account_transfer_over_transaction(const unittest_trans std::vector rederived_output_enote_proposals; encrypted_payment_id_t rederived_encrypted_payment_id; size_t change_index; + std::unordered_map normal_payments_indices; get_output_enote_proposals(tx_proposal.normal_payment_proposals, modified_selfsend_payment_proposals, *parsed_encrypted_payment_id, @@ -213,7 +214,8 @@ static void subtest_multi_account_transfer_over_transaction(const unittest_trans parsed_key_images.at(0), rederived_output_enote_proposals, rederived_encrypted_payment_id, - change_index); + change_index, + normal_payments_indices); EXPECT_EQ(*parsed_encrypted_payment_id, rederived_encrypted_payment_id); ASSERT_EQ(parsed_enotes.size(), rederived_output_enote_proposals.size()); for (size_t enote_idx = 0; enote_idx < parsed_enotes.size(); ++enote_idx) diff --git a/tests/unit_tests/carrot_legacy.cpp b/tests/unit_tests/carrot_legacy.cpp index a9387d5..5923ec7 100644 --- a/tests/unit_tests/carrot_legacy.cpp +++ b/tests/unit_tests/carrot_legacy.cpp @@ -188,6 +188,7 @@ static void subtest_legacy_2out_transfer_get_output_enote_proposals_completeness std::vector enote_proposals; encrypted_payment_id_t encrypted_payment_id; size_t change_index; + std::unordered_map normal_payments_indices; get_output_enote_proposals({bob_payment_proposal}, {alice_payment_proposal}, gen_encrypted_payment_id(), @@ -196,7 +197,8 @@ static void subtest_legacy_2out_transfer_get_output_enote_proposals_completeness tx_first_key_image, enote_proposals, encrypted_payment_id, - change_index); + change_index, + normal_payments_indices); ASSERT_EQ(2, enote_proposals.size()); // 2-out tx diff --git a/tests/unit_tests/carrot_sparc.cpp b/tests/unit_tests/carrot_sparc.cpp index 12f362e..9b46a0f 100644 --- a/tests/unit_tests/carrot_sparc.cpp +++ b/tests/unit_tests/carrot_sparc.cpp @@ -86,6 +86,7 @@ std::tuple, crypto::public_key> make_origin_ .randomness = randomness }, tx_first_key_image, + nullptr, // s_view_balance_dev enote_proposal_out, encrypted_payment_id_out );