implement sparc return address functionality
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -161,6 +161,7 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
|
||||
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
|
||||
encrypted_payment_id_t &encrypted_payment_id_out,
|
||||
size_t &change_index_out,
|
||||
std::unordered_map<crypto::public_key, size_t> &normal_payments_indices_out,
|
||||
std::vector<std::pair<bool, std::size_t>> *payment_proposal_order_out)
|
||||
{
|
||||
output_enote_proposals_out.clear();
|
||||
@@ -203,6 +204,10 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
|
||||
// D^other_e
|
||||
std::optional<mx25519_pubkey> other_enote_ephemeral_pubkey;
|
||||
|
||||
|
||||
// map destinations to output keys to be able to find the indices of these outputs in tx
|
||||
std::unordered_map<crypto::public_key, crypto::public_key> 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<CarrotPaymentProposalV1> &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<CarrotPaymentProposalV1> &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<CarrotPaymentProposalV1> &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
|
||||
|
||||
@@ -111,6 +111,7 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
|
||||
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
|
||||
encrypted_payment_id_t &encrypted_payment_id_out,
|
||||
size_t &change_index_out,
|
||||
std::unordered_map<crypto::public_key, size_t> &normal_payments_indices_out,
|
||||
std::vector<std::pair<bool, std::size_t>> *payment_proposal_order_out = nullptr);
|
||||
/**
|
||||
* brief: get_coinbase_output_enotes - convert a *finalized* set of payment proposals into coinbase output enotes
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
/**
|
||||
|
||||
@@ -197,18 +197,27 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
|
||||
const std::vector<crypto::key_image> &key_images,
|
||||
const std::vector<cryptonote::tx_source_entry> &sources,
|
||||
const rct::xmr_amount fee,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const size_t change_index,
|
||||
const std::vector<uint8_t> 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<CarrotE
|
||||
}
|
||||
|
||||
//outputs
|
||||
size_t i = 0;
|
||||
for (const CarrotEnoteV1 &enote : enotes)
|
||||
{
|
||||
//K_o,vt,anchor_enc
|
||||
@@ -249,6 +259,14 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
|
||||
|
||||
//C_a
|
||||
tx.rct_signatures.outPk.push_back(rct::ctkey{rct::key{}, enote.amount_commitment});
|
||||
|
||||
//K_return
|
||||
if (i != change_index) {
|
||||
crypto::public_key K_return;
|
||||
memcpy(K_return.data, enote.return_enc.bytes, sizeof(crypto::public_key));
|
||||
tx.return_address_list.push_back(K_return);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
//ephemeral pubkeys: D_e
|
||||
|
||||
@@ -104,6 +104,9 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
|
||||
const std::vector<crypto::key_image> &key_images,
|
||||
const std::vector<cryptonote::tx_source_entry> &sources,
|
||||
const rct::xmr_amount fee,
|
||||
const cryptonote::transaction_type tx_type,
|
||||
const size_t change_index,
|
||||
const std::vector<uint8_t> 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
|
||||
|
||||
@@ -60,6 +60,7 @@ void get_output_enote_proposals_from_proposal_v1(const CarrotTransactionProposal
|
||||
|
||||
// derive enote proposals
|
||||
size_t change_index;
|
||||
std::unordered_map<crypto::public_key, size_t> 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
|
||||
|
||||
@@ -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<carrot::CarrotPaymentProposalV1> &proposals,
|
||||
const crypto::key_image &tx_first_key_image,
|
||||
const size_t change_index,
|
||||
const std::unordered_map<crypto::public_key, size_t> &normal_payments_indices,
|
||||
std::vector<uint8_t> &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<carrot::RCTOutputEnoteProposal> output_enote_proposals;
|
||||
carrot::encrypted_payment_id_t encrypted_payment_id;
|
||||
size_t change_index;
|
||||
std::unordered_map<crypto::public_key, size_t> 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<uint8_t> 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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<RCTOutputEnoteProposal> enote_proposals;
|
||||
encrypted_payment_id_t encrypted_payment_id;
|
||||
size_t change_index;
|
||||
std::unordered_map<crypto::public_key, size_t> 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
|
||||
|
||||
|
||||
@@ -375,6 +375,7 @@ TEST(carrot_fcmp, receive_scan_spend_and_verify_serialized_carrot_tx)
|
||||
std::vector<RCTOutputEnoteProposal> output_enote_proposals;
|
||||
encrypted_payment_id_t encrypted_payment_id;
|
||||
size_t change_index;
|
||||
std::unordered_map<crypto::public_key, size_t> 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<crypto::public_key> 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);
|
||||
|
||||
@@ -205,6 +205,7 @@ static void subtest_multi_account_transfer_over_transaction(const unittest_trans
|
||||
std::vector<RCTOutputEnoteProposal> rederived_output_enote_proposals;
|
||||
encrypted_payment_id_t rederived_encrypted_payment_id;
|
||||
size_t change_index;
|
||||
std::unordered_map<crypto::public_key, size_t> 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)
|
||||
|
||||
@@ -188,6 +188,7 @@ static void subtest_legacy_2out_transfer_get_output_enote_proposals_completeness
|
||||
std::vector<RCTOutputEnoteProposal> enote_proposals;
|
||||
encrypted_payment_id_t encrypted_payment_id;
|
||||
size_t change_index;
|
||||
std::unordered_map<crypto::public_key, size_t> 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
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ std::tuple<std::vector<RCTOutputEnoteProposal>, crypto::public_key> make_origin_
|
||||
.randomness = randomness
|
||||
},
|
||||
tx_first_key_image,
|
||||
nullptr, // s_view_balance_dev
|
||||
enote_proposal_out,
|
||||
encrypted_payment_id_out
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user