Merge branch 'carrot-integration' of https://github.com/salvium/salvium into carrot-integration

This commit is contained in:
Some Random Crypto Guy
2025-06-12 14:35:39 +01:00
26 changed files with 383 additions and 189 deletions
+2 -2
View File
@@ -160,8 +160,8 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
const crypto::key_image &tx_first_key_image,
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
encrypted_payment_id_t &encrypted_payment_id_out,
std::vector<std::pair<bool, std::size_t>> *payment_proposal_order_out,
size_t change_index_out)
size_t &change_index_out,
std::vector<std::pair<bool, std::size_t>> *payment_proposal_order_out)
{
output_enote_proposals_out.clear();
encrypted_payment_id_out = {{0}};
+2 -2
View File
@@ -110,8 +110,8 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
const crypto::key_image &tx_first_key_image,
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
encrypted_payment_id_t &encrypted_payment_id_out,
std::vector<std::pair<bool, std::size_t>> *payment_proposal_order_out = nullptr,
size_t change_index_out = 0);
size_t &change_index_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
* param: normal_payment_proposals -
+3
View File
@@ -332,6 +332,7 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal,
// 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;
}
//-------------------------------------------------------------------------------------------------------------------
@@ -399,6 +400,7 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo
// 8. save the enote ephemeral pubkey, first tx key image, and amount
output_enote_out.enote.enote_ephemeral_pubkey = enote_ephemeral_pubkey;
output_enote_out.enote.tx_first_key_image = tx_first_key_image;
output_enote_out.enote.asset_type = "SAL1";
output_enote_out.amount = proposal.amount;
}
//-------------------------------------------------------------------------------------------------------------------
@@ -526,6 +528,7 @@ void get_output_proposal_internal_v1(const CarrotPaymentProposalSelfSendV1 &prop
// 9. save the enote ephemeral pubkey, first tx key image, and amount
output_enote_out.enote.enote_ephemeral_pubkey = enote_ephemeral_pubkey;
output_enote_out.enote.tx_first_key_image = tx_first_key_image;
output_enote_out.enote.asset_type = "SAL1";
output_enote_out.amount = proposal.amount;
}
//-------------------------------------------------------------------------------------------------------------------
+20 -7
View File
@@ -35,6 +35,7 @@
#include "carrot_core/payment_proposal.h"
#include "common/container_helpers.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
#include "cryptonote_config.h"
//third party headers
@@ -55,6 +56,9 @@ template <class EnoteContainer>
static void store_carrot_ephemeral_pubkeys_to_extra(const EnoteContainer &enotes, std::vector<uint8_t> &extra_inout)
{
const size_t nouts = enotes.size();
if (nouts == 0)
return;
const bool use_shared_ephemeral_pubkey = nouts == 2 && 0 == memcmp(
&enotes.front().enote_ephemeral_pubkey,
&enotes.back().enote_ephemeral_pubkey,
@@ -191,11 +195,13 @@ bool try_load_carrot_extra_v1(
//-------------------------------------------------------------------------------------------------------------------
cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotEnoteV1> &enotes,
const std::vector<crypto::key_image> &key_images,
const std::vector<cryptonote::tx_source_entry> &sources,
const rct::xmr_amount fee,
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");
cryptonote::transaction tx;
tx.pruned = true;
@@ -210,13 +216,19 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
tx.rct_signatures.outPk.reserve(nouts);
//inputs
for (const crypto::key_image &ki : key_images)
for (size_t i = 0; i < nins; ++i)
{
// collect key offsets
std::vector<uint64_t> key_offsets;
for(const auto &out_entry: sources[i].outputs)
key_offsets.push_back(out_entry.first);
//L
tx.vin.emplace_back(cryptonote::txin_to_key{ //@TODO: can save 2 bytes by using slim input type
.amount = 0,
.key_offsets = {},
.k_image = ki
.key_offsets = cryptonote::absolute_output_offsets_to_relative(key_offsets),
.k_image = key_images.at(i),
.asset_type = "SAL1"
});
}
@@ -227,7 +239,8 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
tx.vout.push_back(cryptonote::tx_out{0, cryptonote::txout_to_carrot_v1{
.key = enote.onetime_address,
.view_tag = enote.view_tag,
.encrypted_janus_anchor = enote.anchor_enc
.encrypted_janus_anchor = enote.anchor_enc,
.asset_type = enote.asset_type,
}});
//a_enc
@@ -360,11 +373,11 @@ bool try_load_carrot_from_transaction_v1(const cryptonote::transaction &tx,
cryptonote::transaction store_carrot_to_coinbase_transaction_v1(
const std::vector<CarrotCoinbaseEnoteV1> &enotes,
const cryptonote::blobdata &extra_nonce,
const cryptonote::transaction_type &tx_type)
const cryptonote::transaction_type &tx_type,
const std::uint64_t block_index)
{
CARROT_CHECK_AND_THROW(tx_type == cryptonote::transaction_type::MINER || tx_type == cryptonote::transaction_type::PROTOCOL, invalid_tx_type, "invalid tx_type : is not MINER or PROTOCOL");
const size_t nouts = enotes.size();
const std::uint64_t block_index = enotes.at(0).block_index;
cryptonote::transaction tx;
tx.type = tx_type;
@@ -427,7 +440,7 @@ cryptonote::transaction make_single_enote_carrot_coinbase_transaction_v1(const C
std::vector<CarrotCoinbaseEnoteV1> enotes(1);
get_coinbase_output_proposal_v1(payment_proposal, block_index, enotes.front());
return store_carrot_to_coinbase_transaction_v1(enotes, extra_nonce, cryptonote::transaction_type::MINER);
return store_carrot_to_coinbase_transaction_v1(enotes, extra_nonce, cryptonote::transaction_type::MINER, block_index);
}
//-------------------------------------------------------------------------------------------------------------------
bool try_load_carrot_coinbase_enote_from_transaction_v1(const cryptonote::transaction &tx,
+5 -1
View File
@@ -34,6 +34,7 @@
#include "cryptonote_basic/blobdatatype.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/tx_extra.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
//third party headers
@@ -101,6 +102,7 @@ bool try_load_carrot_extra_v1(
*/
cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotEnoteV1> &enotes,
const std::vector<crypto::key_image> &key_images,
const std::vector<cryptonote::tx_source_entry> &sources,
const rct::xmr_amount fee,
const encrypted_payment_id_t encrypted_payment_id);
/**
@@ -133,12 +135,14 @@ bool try_load_carrot_from_transaction_v1(const cryptonote::transaction &tx,
* brief: store_carrot_to_coinbase_transaction_v1 - store coinbase Carrot info to a cryptonote::transaction
* param: enotes -
* param: extra_nonce -
* param: block_index -
* return: a full coinbase transaction containing given Carrot information
*/
cryptonote::transaction store_carrot_to_coinbase_transaction_v1(
const std::vector<CarrotCoinbaseEnoteV1> &enotes,
const cryptonote::blobdata &extra_nonce,
const cryptonote::transaction_type &tx_type);
const cryptonote::transaction_type &tx_type,
const std::uint64_t block_index);
/**
* brief: make_single_enote_carrot_coinbase_transaction_v1 - store one coinbase Carrot enote to a cryptonote::transaction
* param: destination -
+3
View File
@@ -59,6 +59,7 @@ void get_output_enote_proposals_from_proposal_v1(const CarrotTransactionProposal
selfsend_payment_proposal_cores.push_back(selfsend_payment_proposal.proposal);
// derive enote proposals
size_t change_index;
get_output_enote_proposals(tx_proposal.normal_payment_proposals,
selfsend_payment_proposal_cores,
tx_proposal.dummy_encrypted_payment_id,
@@ -67,6 +68,7 @@ void get_output_enote_proposals_from_proposal_v1(const CarrotTransactionProposal
tx_proposal.key_images_sorted.at(0),
output_enote_proposals_out,
encrypted_payment_id_out,
change_index,
payment_proposal_order_out);
}
//-------------------------------------------------------------------------------------------------------------------
@@ -119,6 +121,7 @@ void make_pruned_transaction_from_proposal_v1(const CarrotTransactionProposalV1
// serialize tx
pruned_tx_out = store_carrot_to_transaction_v1(enotes,
tx_proposal.key_images_sorted,
tx_proposal.sources,
tx_proposal.fee,
encrypted_payment_id);
+3
View File
@@ -31,6 +31,7 @@
//local headers
#include "carrot_core/payment_proposal.h"
#include "subaddress_index.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
//third party headers
@@ -70,6 +71,8 @@ struct CarrotTransactionProposalV1
{
/// Key images sorted in std::greater order
std::vector<crypto::key_image> key_images_sorted;
// sources in the same order as key_images_sorted.
std::vector<cryptonote::tx_source_entry> sources;
/// Payment proposals to be converted into output enotes
std::vector<CarrotPaymentProposalV1> normal_payment_proposals;
+6 -7
View File
@@ -115,6 +115,7 @@ std::uint64_t get_carrot_default_tx_extra_size(const std::size_t n_outputs)
void make_carrot_transaction_proposal_v1(const std::vector<CarrotPaymentProposalV1> &normal_payment_proposals_in,
const std::vector<CarrotPaymentProposalVerifiableSelfSendV1> &selfsend_payment_proposals_in,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
select_inputs_func_t &&select_inputs,
carve_fees_and_balance_func_t &&carve_fees_and_balance,
@@ -172,13 +173,7 @@ void make_carrot_transaction_proposal_v1(const std::vector<CarrotPaymentProposal
std::map<size_t, rct::xmr_amount> fee_per_input_count;
for (size_t num_ins = CARROT_MIN_TX_INPUTS; num_ins <= CARROT_MAX_TX_INPUTS; ++num_ins)
{
const uint64_t tx_weight = get_fcmppp_tx_weight(num_ins, num_outs, tx_extra_size);
CHECK_AND_ASSERT_THROW_MES(tx_weight != std::numeric_limits<uint64_t>::max(),
"make_carrot_transaction_proposal_v1: invalid weight returned for ins=" << num_ins
<< " outs=" << num_outs << " extra_size=" << tx_extra_size);
CHECK_AND_ASSERT_THROW_MES(std::numeric_limits<uint64_t>::max() / tx_weight > fee_per_weight,
"make_carrot_transaction_proposal_v1: overflow in fee calculation");
const rct::xmr_amount fee = tx_weight * fee_per_weight;
const rct::xmr_amount fee = estimate_fee_carrot(num_ins, 15, num_outs, tx_extra_size, true, true, true, true, fee_per_weight, fee_quantization_mask);
fee_per_input_count.emplace(num_ins, fee);
}
@@ -237,6 +232,7 @@ void make_carrot_transaction_proposal_v1_transfer(
const std::vector<CarrotPaymentProposalV1> &normal_payment_proposals,
const std::vector<CarrotPaymentProposalVerifiableSelfSendV1> &selfsend_payment_proposals_in,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
select_inputs_func_t &&select_inputs,
const crypto::public_key &change_address_spend_pubkey,
@@ -387,6 +383,7 @@ void make_carrot_transaction_proposal_v1_transfer(
make_carrot_transaction_proposal_v1(normal_payment_proposals,
selfsend_payment_proposals,
fee_per_weight,
fee_quantization_mask,
extra,
std::forward<select_inputs_func_t>(select_inputs),
std::move(carve_fees_and_balance),
@@ -399,6 +396,7 @@ void make_carrot_transaction_proposal_v1_sweep(
const std::vector<CarrotPaymentProposalV1> &normal_payment_proposals,
const std::vector<CarrotPaymentProposalVerifiableSelfSendV1> &selfsend_payment_proposals,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
std::vector<CarrotSelectedInput> &&selected_inputs,
const crypto::public_key &change_address_spend_pubkey,
@@ -477,6 +475,7 @@ void make_carrot_transaction_proposal_v1_sweep(
make_carrot_transaction_proposal_v1(normal_payment_proposals,
selfsend_payment_proposals,
fee_per_weight,
fee_quantization_mask,
extra,
std::move(select_inputs),
std::move(carve_fees_and_balance),
+103
View File
@@ -82,9 +82,110 @@ static inline std::size_t get_fcmppp_tx_weight(const std::size_t num_inputs,
return 200 + num_inputs * 1000 + num_outputs * 100 + tx_extra_size;
}
static size_t estimate_rct_tx_size_carrot(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags)
{
size_t size = 0;
// tx prefix
// first few bytes
size += 1 + 6;
// vin
size += n_inputs * (1+6+4+(mixin+1)*2+32);
// vout
size += n_outputs * (3+4+16+32);
// extra
size += extra_size;
// rct signatures
// type
size += 1;
// rangeSigs
if (bulletproof || bulletproof_plus)
{
size_t log_padded_outputs = 0;
while ((1<<log_padded_outputs) < n_outputs)
++log_padded_outputs;
size += (2 * (6 + log_padded_outputs) + (bulletproof_plus ? 6 : (4 + 5))) * 32 + 3;
}
else
size += (2*64*32+32+64*32) * n_outputs;
// MGs/CLSAGs
if (clsag)
size += n_inputs * (64 * (mixin+1) + 64);
else
size += n_inputs * (64 * (mixin+1) + 32);
if (use_view_tags)
size += n_outputs * sizeof(crypto::view_tag);
// mixRing - not serialized, can be reconstructed
/* size += 2 * 32 * (mixin+1) * n_inputs; */
// pseudoOuts
size += 32 * n_inputs;
// ecdhInfo
size += 8 * n_outputs;
// outPk - only commitment is saved
size += 32 * n_outputs;
// txnFee
size += 4;
// p_r
size += 32;
// 2 zk proof
size += (2 * 96);
LOG_PRINT_L2("estimated " << (bulletproof_plus ? "bulletproof plus" : bulletproof ? "bulletproof" : "borromean") << " rct tx size for " << n_inputs << " inputs with ring size " << (mixin+1) << " and " << n_outputs << " outputs: " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)");
return size;
}
static size_t estimate_tx_size_carrot(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags)
{
return estimate_rct_tx_size_carrot(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
}
static uint64_t estimate_tx_weigh_carrot(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags)
{
size_t size = estimate_tx_size_carrot(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
if ((bulletproof || bulletproof_plus) && n_outputs > 2)
{
const uint64_t bp_base = (32 * ((bulletproof_plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
size_t log_padded_outputs = 2;
while ((1<<log_padded_outputs) < n_outputs)
++log_padded_outputs;
uint64_t nlr = 2 * (6 + log_padded_outputs);
const uint64_t bp_size = 32 * ((bulletproof_plus ? 6 : 9) + nlr);
const uint64_t bp_clawback = (bp_base * (1<<log_padded_outputs) - bp_size) * 4 / 5;
MDEBUG("clawback on size " << size << ": " << bp_clawback);
size += bp_clawback;
}
return size;
}
static uint64_t calculate_fee_from_weight_carrot(uint64_t base_fee, uint64_t weight, uint64_t fee_quantization_mask)
{
uint64_t fee = weight * base_fee;
fee = (fee + fee_quantization_mask - 1) / fee_quantization_mask * fee_quantization_mask;
return fee;
}
static uint64_t estimate_fee_carrot(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask)
{
const size_t estimated_tx_weight = estimate_tx_weigh_carrot(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
return calculate_fee_from_weight_carrot(base_fee, estimated_tx_weight, fee_quantization_mask);
}
void make_carrot_transaction_proposal_v1(const std::vector<CarrotPaymentProposalV1> &normal_payment_proposals,
const std::vector<CarrotPaymentProposalVerifiableSelfSendV1> &selfsend_payment_proposals,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
select_inputs_func_t &&select_inputs,
carve_fees_and_balance_func_t &&carve_fees_and_balance,
@@ -96,6 +197,7 @@ void make_carrot_transaction_proposal_v1_transfer(
const std::vector<CarrotPaymentProposalV1> &normal_payment_proposals,
const std::vector<CarrotPaymentProposalVerifiableSelfSendV1> &selfsend_payment_proposals,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
select_inputs_func_t &&select_inputs,
const crypto::public_key &change_address_spend_pubkey,
@@ -108,6 +210,7 @@ void make_carrot_transaction_proposal_v1_sweep(
const std::vector<CarrotPaymentProposalV1> &normal_payment_proposals,
const std::vector<CarrotPaymentProposalVerifiableSelfSendV1> &selfsend_payment_proposals,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
std::vector<CarrotSelectedInput> &&selected_inputs,
const crypto::public_key &change_address_spend_pubkey,
@@ -110,7 +110,11 @@ namespace cryptonote
uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
{
const rct::rctSig &rv = tx.rct_signatures;
const bool plus = (rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeFullProofs);
const bool plus = (
rv.type == rct::RCTTypeBulletproofPlus ||
rv.type == rct::RCTTypeFullProofs ||
rv.type == rct::RCTTypeSalviumZero ||
rv.type == rct::RCTTypeSalviumOne);
const uint64_t bp_base = (32 * ((plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
const size_t n_outputs = tx.vout.size();
if (n_padded_outputs <= 2)
+12 -1
View File
@@ -3789,7 +3789,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
}
}
}
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeFullProofs || rv.type == rct::RCTTypeSalviumOne)
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeFullProofs || rv.type == rct::RCTTypeSalviumZero)
{
if (!tx.pruned)
{
@@ -3799,6 +3799,17 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
rv.p.CLSAGs[n].I = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
}
}
}
else if (rv.type == rct::RCTTypeSalviumOne)
{
if (!tx.pruned)
{
CHECK_AND_ASSERT_MES(rv.p.TCLSAGs.size() == tx.vin.size(), false, "Bad TCLSAGs size");
for (size_t n = 0; n < tx.vin.size(); ++n)
{
rv.p.TCLSAGs[n].I = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
}
}
}
else
{
+5 -3
View File
@@ -411,10 +411,12 @@ namespace cryptonote
};
// Build the proposal
get_coinbase_output_proposal_v1(payment_proposal, height, enotes.back());
carrot::CarrotCoinbaseEnoteV1 e;
get_coinbase_output_proposal_v1(payment_proposal, height, e);
enotes.push_back(e);
}
tx = store_carrot_to_coinbase_transaction_v1(enotes, std::string{}, cryptonote::transaction_type::PROTOCOL);
tx = store_carrot_to_coinbase_transaction_v1(enotes, std::string{}, cryptonote::transaction_type::PROTOCOL, height);
tx.amount_burnt = 0;
tx.invalidate_hashes();
}
@@ -90,11 +90,13 @@ namespace cryptonote
uint64_t amount; //money
bool rct; //true if the output is rct
bool carrot; //true if the output is a carrot output
bool coinbase; //true if the output is a coinbase output
rct::key mask; //ringct amount mask
rct::multisig_kLRki multisig_kLRki; //multisig info
std::string asset_type;
crypto::key_image first_rct_key_image;
crypto::public_key address_spend_pubkey; // the spend public key of the address that this source is for.
uint64_t block_index;
origin_data origin_tx_data;
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
+10 -2
View File
@@ -59,7 +59,10 @@ static bool expand_tx_and_ver_rct_non_sem(transaction& tx, const rct::ctkeyM& mi
VER_ASSERT(rv.mixRing == mix_ring, "Failed to check ringct signatures: mismatched pubkeys/mixRing");
// Check CLSAG/MLSAG size against transaction input
const size_t n_sigs = rct::is_rct_clsag(rv.type) ? rv.p.CLSAGs.size() : rv.p.MGs.size();
const size_t n_sigs = rct::is_rct_tclsag(rv.type) ? rv.p.TCLSAGs.size() :
(
rct::is_rct_clsag(rv.type) ? rv.p.CLSAGs.size() : rv.p.MGs.size()
);
VER_ASSERT(n_sigs == tx.vin.size(), "Failed to check ringct signatures: mismatched input sigs/vin sizes");
// For each input, check that the key images were copied into the expanded RCT sig correctly
@@ -67,7 +70,12 @@ static bool expand_tx_and_ver_rct_non_sem(transaction& tx, const rct::ctkeyM& mi
{
const crypto::key_image& nth_vin_image = boost::get<txin_to_key>(tx.vin[n]).k_image;
if (rct::is_rct_clsag(rv.type))
if (rct::is_rct_tclsag(rv.type))
{
const bool ki_match = 0 == memcmp(&nth_vin_image, &rv.p.TCLSAGs[n].I, 32);
VER_ASSERT(ki_match, "Failed to check ringct signatures: mismatched TCLSAG key image");
}
else if (rct::is_rct_clsag(rv.type))
{
const bool ki_match = 0 == memcmp(&nth_vin_image, &rv.p.CLSAGs[n].I, 32);
VER_ASSERT(ki_match, "Failed to check ringct signatures: mismatched CLSAG key image");
+21 -24
View File
@@ -1507,26 +1507,26 @@ namespace rct {
//RCT simple
//for post-rct only
rctSig genRctSimpleCarrot(
const key &message,
const carrot_ctkeyV & inSk,
const keyV & destinations,
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const std::vector<xmr_amount> & inamounts,
const std::vector<xmr_amount> & outamounts,
xmr_amount txnFee,
const ctkeyM & mixRing,
const std::vector<unsigned int> & index,
const ctkeyV &outSk,
const RCTConfig &rct_config,
hw::device &hwdev,
const rct::salvium_data_t &salvium_data,
const key &x_change,
const key &y_change,
const size_t change_index
)
void genRctSimpleCarrot(
const key &message,
const carrot_ctkeyV & inSk,
const keyV & destinations,
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const std::vector<xmr_amount> & inamounts,
const std::vector<xmr_amount> & outamounts,
xmr_amount txnFee,
const ctkeyM & mixRing,
const std::vector<unsigned int> & index,
const ctkeyV &outSk,
const RCTConfig &rct_config,
hw::device &hwdev,
const rct::salvium_data_t &salvium_data,
const key &x_change,
const key &y_change,
const size_t change_index,
rctSig &rv)
{
CHECK_AND_ASSERT_THROW_MES(rct_config.range_proof_type == RangeProofPaddedBulletproof, "Borromean range proofs no longer supported");
CHECK_AND_ASSERT_THROW_MES(destination_asset_types.size() == destinations.size(), "Different number of amount_keys/destinations");
@@ -1539,7 +1539,6 @@ namespace rct {
CHECK_AND_ASSERT_THROW_MES(index[n] < mixRing[n].size(), "Bad index into mixRing");
}
rctSig rv;
switch (rct_config.bp_version)
{
case 0:
@@ -1615,8 +1614,6 @@ namespace rct {
else
rv.p.TCLSAGs[i] = proveRctTCLSAGSimple(full_message, rv.mixRing[i], inSk[i].x, inSk[i].y, inSk[i].mask, a[i], pseudoOuts[i], index[i], hwdev);
}
return rv;
}
//RCT simple
@@ -2126,7 +2123,7 @@ namespace rct {
const keyV &pseudoOuts = bulletproof || bulletproof_plus ? rv.p.pseudoOuts : rv.pseudoOuts;
const key message = get_pre_mlsag_hash(rv, hw::get_device("default"));
results.clear();
results.resize(rv.mixRing.size());
for (size_t i = 0 ; i < rv.mixRing.size() ; i++) {
+3 -2
View File
@@ -138,7 +138,7 @@ namespace rct {
// must know the destination private key to find the correct amount, else will return a random number
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const std::vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & amounts, const keyV &amount_keys, const int mixin, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRctSimpleCarrot(
void genRctSimpleCarrot(
const key &message,
const carrot_ctkeyV & inSk,
const keyV & destinations,
@@ -156,7 +156,8 @@ namespace rct {
const rct::salvium_data_t &salvium_data,
const key &x_change,
const key &y_change,
const size_t change_index
const size_t change_index,
rctSig &rv
);
rctSig genRctSimple(
const key & message,
+3 -3
View File
@@ -483,7 +483,7 @@ namespace rct {
}
ar.end_array();
FIELD(p_r)
if (type == RCTTypeSalviumZero)
if (type == RCTTypeSalviumZero || type == RCTTypeSalviumOne)
{
FIELD(salvium_data)
}
@@ -597,11 +597,11 @@ namespace rct {
ar.end_array();
ar.tag("c1");
FIELDS(CLSAGs[i].c1)
FIELDS(TCLSAGs[i].c1)
// CLSAGs[i].I not saved, it can be reconstructed
ar.tag("D");
FIELDS(CLSAGs[i].D)
FIELDS(TCLSAGs[i].D)
ar.end_object();
if (inputs - i > 1)
+2 -2
View File
@@ -7326,8 +7326,8 @@ bool simple_wallet::transfer_main(
float days = locked_blocks / 720.0f;
prompt << boost::format(tr(".\nThis transaction (including %s change) will unlock in %llu blocks, approximately %s days (assuming 2 minutes per block)")) % cryptonote::print_money(change) % ((unsigned long long)unlock_block) % days;
}
if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
return false;
// if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
// return false;
bool default_ring_size = true;
for (const auto &ptx: ptx_vector)
{
+154 -121
View File
@@ -128,7 +128,8 @@ static bool build_payment_proposals(std::vector<carrot::CarrotPaymentProposalV1>
normal_payment_proposals_inout.push_back(carrot::CarrotPaymentProposalV1{
.destination = dest,
.amount = tx_dest_entry.amount,
.randomness = carrot::gen_janus_anchor()
.randomness = carrot::gen_janus_anchor(),
.asset_type = tx_dest_entry.asset_type
});
}
@@ -293,20 +294,120 @@ carrot::select_inputs_func_t make_wallet2_single_transfer_input_selector(
};
}
//-------------------------------------------------------------------------------------------------------------------
std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposals_wallet2_transfer(
std::vector<cryptonote::tx_source_entry> get_sources(
const wallet2::transfer_container &transfers,
const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> &subaddress_map,
const std::vector<std::size_t> &selected_transfers,
const std::string &source_asset,
wallet2 &w
) {
// get decoys
const size_t fake_outputs_count = 15;
std::vector<std::vector<tools::wallet2::get_outs_entry>> outs;
std::unordered_set<crypto::public_key> valid_public_keys_cache;
w.get_outs(outs, selected_transfers, fake_outputs_count, true, valid_public_keys_cache); // may throw
LOG_PRINT_L2("preparing outputs");
size_t i = 0, out_index = 0;
std::vector<cryptonote::tx_source_entry> sources;
for(size_t idx: selected_transfers)
{
sources.resize(sources.size()+1);
cryptonote::tx_source_entry& src = sources.back();
const wallet2::transfer_details& td = transfers[idx];
// Sanity check the asset_type for this TD is correct
THROW_WALLET_EXCEPTION_IF(td.asset_type != source_asset, error::wallet_internal_error, "Input has wrong asset_type - expected " + source_asset + " but found " + td.asset_type);
src.amount = td.amount();
src.rct = td.is_rct();
src.carrot = td.is_carrot();
src.coinbase = td.m_tx.vin[0].type() == typeid(cryptonote::txin_gen);
src.block_index = td.m_block_height;
src.asset_type = td.asset_type;
// Create the origin TX data
if (td.m_td_origin_idx != (uint64_t)-1) {
THROW_WALLET_EXCEPTION_IF(td.m_td_origin_idx >= w.get_num_transfer_details(), error::wallet_internal_error, "cannot locate return_payment origin index in m_transfers");
const wallet2::transfer_details& td_origin = w.get_transfer_details(td.m_td_origin_idx);
src.origin_tx_data.tx_type = td_origin.m_tx.type;
src.origin_tx_data.tx_pub_key = cryptonote::get_tx_pub_key_from_extra(td_origin.m_tx);
src.origin_tx_data.output_index = td_origin.m_internal_output_index;
}
//paste mixin transaction
THROW_WALLET_EXCEPTION_IF(outs.size() < out_index + 1 , error::wallet_internal_error, "outs.size() < out_index + 1");
THROW_WALLET_EXCEPTION_IF(outs[out_index].size() < fake_outputs_count , error::wallet_internal_error, "fake_outputs_count > random outputs found");
typedef cryptonote::tx_source_entry::output_entry tx_output_entry;
for (size_t n = 0; n < fake_outputs_count + 1; ++n)
{
tx_output_entry oe;
oe.first = std::get<0>(outs[out_index][n]);
oe.second.dest = rct::pk2rct(std::get<1>(outs[out_index][n]));
oe.second.mask = std::get<2>(outs[out_index][n]);
src.outputs.push_back(oe);
}
++i;
//paste real transaction to the random index
auto it_to_replace = std::find_if(src.outputs.begin(), src.outputs.end(), [&](const tx_output_entry& a)
{
// HERE BE DRAGONS!!!
// SRCG: ring tweak to indexed per asset_type - DO NOT COMMIT UNTIL IT IS ALL WORKING
//return a.first == td.m_global_output_index;
return a.first == td.m_asset_type_output_index;
// LAND AHOY!!!
});
THROW_WALLET_EXCEPTION_IF(it_to_replace == src.outputs.end(), error::wallet_internal_error,
"real output not found");
tx_output_entry real_oe;
// HERE BE DRAGONS!!!
// SRCG: ring tweak to indexed per asset_type - DO NOT COMMIT UNTIL IT IS ALL WORKING
//real_oe.first = td.m_global_output_index;
real_oe.first = td.m_asset_type_output_index;
// LAND AHOY!!!
real_oe.second.dest = rct::pk2rct(td.get_public_key());
real_oe.second.mask = rct::commit(td.amount(), td.m_mask);
*it_to_replace = real_oe;
src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index);
src.real_out_additional_tx_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
src.real_output = it_to_replace - src.outputs.begin();
src.real_output_in_tx_index = td.m_internal_output_index;
src.mask = td.m_mask;
src.address_spend_pubkey = td.m_recovered_spend_pubkey;
if (td.m_tx.vin[0].type() == typeid(cryptonote::txin_to_key)) {
src.first_rct_key_image = boost::get<cryptonote::txin_to_key>(td.m_tx.vin[0]).k_image;
}
if (false) // w.m_multisig // TODO:
// note: multisig_kLRki is a legacy struct, currently only used as a key image shuttle into the multisig tx builder
src.multisig_kLRki = {.k = {}, .L = {}, .R = {}, .ki = rct::ki2rct(td.m_key_image)};
else
src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
detail::print_source_entry(src);
++out_index;
}
LOG_PRINT_L2("outputs prepared");
return sources;
}
//-------------------------------------------------------------------------------------------------------------------
std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposals_wallet2_transfer(
wallet2 &w,
std::vector<cryptonote::tx_destination_entry> dsts,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
const std::uint32_t subaddr_account,
const uint32_t subaddr_account,
const std::set<uint32_t> &subaddr_indices,
const rct::xmr_amount ignore_above,
const rct::xmr_amount ignore_below,
wallet2::unique_index_container subtract_fee_from_outputs,
const std::uint64_t top_block_index)
{
wallet2::transfer_container unused_transfers(transfers);
wallet2::transfer_container unused_transfers;
w.get_transfers(unused_transfers);
const auto subaddress_map = w.get_subaddress_map_ref();
std::vector<carrot::CarrotTransactionProposalV1> tx_proposals;
tx_proposals.reserve(dsts.size() / (FCMP_PLUS_PLUS_MAX_OUTPUTS - 1) + 1);
@@ -346,8 +447,8 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
unused_transfers,
subaddr_account,
subaddr_indices,
ignore_above,
ignore_below,
w.ignore_outputs_above(),
w.ignore_outputs_below(),
top_block_index,
/*allow_carrot_external_inputs_in_normal_transfers=*/true,
/*allow_pre_carrot_inputs_in_normal_transfers=*/true,
@@ -359,6 +460,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
normal_payment_proposals,
selfsend_payment_proposals,
fee_per_weight,
fee_quantization_mask,
extra,
std::move(select_inputs),
change_address_spend_pubkey,
@@ -366,6 +468,13 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
subtractable_normal_payment_proposals,
subtractable_selfsend_payment_proposals,
tx_proposal);
// populate the sources
std::vector<size_t> selected_transfer_indices_sorted;
for (const auto &ki: tx_proposal.key_images_sorted) {
selected_transfer_indices_sorted.push_back(w.get_transfer_details(ki));
}
tx_proposal.sources = get_sources(unused_transfers, selected_transfer_indices_sorted, "SAL1", w);
// update `unused_transfers` for next proposal by removing selected transfers
tools::for_all_in_vector_erase_no_preserve_order_if(unused_transfers,
@@ -400,6 +509,9 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
const rct::xmr_amount fee_per_weight = w.get_base_fee(priority);
MDEBUG("fee_per_weight = " << fee_per_weight << ", from priority = " << priority);
const rct::xmr_amount fee_quantization_mask = w.get_fee_quantization_mask();
MDEBUG("fee_quantization_mask = " << fee_quantization_mask << ", from priority = " << priority);
const std::uint64_t current_chain_height = w.get_blockchain_current_height();
CHECK_AND_ASSERT_THROW_MES(current_chain_height > 0,
@@ -407,15 +519,13 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
const std::uint64_t top_block_index = current_chain_height - 1;
return make_carrot_transaction_proposals_wallet2_transfer(
transfers,
w.get_subaddress_map_ref(),
w,
dsts,
fee_per_weight,
fee_quantization_mask,
extra,
subaddr_account,
subaddr_indices,
w.ignore_outputs_above(),
w.ignore_outputs_below(),
subtract_fee_from_outputs,
top_block_index);
}
@@ -428,6 +538,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
const bool is_subaddress,
const size_t n_dests_per_tx,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
const std::uint64_t top_block_index)
{
@@ -498,6 +609,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
carrot::make_carrot_transaction_proposal_v1_sweep(normal_payment_proposals,
selfsend_payment_proposals,
fee_per_weight,
fee_quantization_mask,
extra,
std::move(selected_inputs),
change_address_spend_pubkey,
@@ -524,6 +636,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
w.get_transfers(transfers);
const rct::xmr_amount fee_per_weight = w.get_base_fee(priority);
const rct::xmr_amount fee_quantization_mask = w.get_fee_quantization_mask();
const std::uint64_t current_chain_height = w.get_blockchain_current_height();
CHECK_AND_ASSERT_THROW_MES(current_chain_height > 0,
@@ -538,6 +651,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
is_subaddress,
n_dests_per_tx,
fee_per_weight,
fee_quantization_mask,
extra,
top_block_index);
}
@@ -550,6 +664,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
const bool is_subaddress,
const size_t n_dests_per_tx,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
const std::uint32_t subaddr_account,
const std::set<uint32_t> &subaddr_indices,
@@ -591,6 +706,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
is_subaddress,
n_dests_per_tx,
fee_per_weight,
fee_quantization_mask,
extra,
top_block_index);
}
@@ -610,6 +726,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
w.get_transfers(transfers);
const rct::xmr_amount fee_per_weight = w.get_base_fee(priority);
const rct::xmr_amount fee_quantization_mask = w.get_fee_quantization_mask();
const std::uint64_t current_chain_height = w.get_blockchain_current_height();
CHECK_AND_ASSERT_THROW_MES(current_chain_height > 0,
@@ -624,110 +741,15 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
is_subaddress,
n_dests_per_tx,
fee_per_weight,
fee_quantization_mask,
extra,
subaddr_account,
subaddr_indices,
top_block_index);
}
std::vector<cryptonote::tx_source_entry> get_sources(
const wallet2::transfer_container &transfers,
const std::vector<std::size_t> &selected_transfers,
const std::string &source_asset,
const wallet2 &w
) {
// get decoys
const size_t fake_outputs_count = 15;
std::vector<std::vector<tools::wallet2::get_outs_entry>> outs;
std::unordered_set<crypto::public_key> valid_public_keys_cache;
wallet2 &w2 = const_cast<tools::wallet2 &>(w);
w2.get_outs(outs, selected_transfers, fake_outputs_count, true, valid_public_keys_cache); // may throw
LOG_PRINT_L2("preparing outputs");
size_t i = 0, out_index = 0;
std::vector<cryptonote::tx_source_entry> sources;
for(size_t idx: selected_transfers)
{
sources.resize(sources.size()+1);
cryptonote::tx_source_entry& src = sources.back();
const wallet2::transfer_details& td = transfers[idx];
// Sanity check the asset_type for this TD is correct
THROW_WALLET_EXCEPTION_IF(td.asset_type != source_asset, error::wallet_internal_error, "Input has wrong asset_type - expected " + source_asset + " but found " + td.asset_type);
src.amount = td.amount();
src.rct = td.is_rct();
src.carrot = td.is_carrot();
src.asset_type = td.asset_type;
// Create the origin TX data
if (td.m_td_origin_idx != (uint64_t)-1) {
THROW_WALLET_EXCEPTION_IF(td.m_td_origin_idx >= w.get_num_transfer_details(), error::wallet_internal_error, "cannot locate return_payment origin index in m_transfers");
const wallet2::transfer_details& td_origin = w.get_transfer_details(td.m_td_origin_idx);
src.origin_tx_data.tx_type = td_origin.m_tx.type;
src.origin_tx_data.tx_pub_key = cryptonote::get_tx_pub_key_from_extra(td_origin.m_tx);
src.origin_tx_data.output_index = td_origin.m_internal_output_index;
}
//paste mixin transaction
THROW_WALLET_EXCEPTION_IF(outs.size() < out_index + 1 , error::wallet_internal_error, "outs.size() < out_index + 1");
THROW_WALLET_EXCEPTION_IF(outs[out_index].size() < fake_outputs_count , error::wallet_internal_error, "fake_outputs_count > random outputs found");
typedef cryptonote::tx_source_entry::output_entry tx_output_entry;
for (size_t n = 0; n < fake_outputs_count + 1; ++n)
{
tx_output_entry oe;
oe.first = std::get<0>(outs[out_index][n]);
oe.second.dest = rct::pk2rct(std::get<1>(outs[out_index][n]));
oe.second.mask = std::get<2>(outs[out_index][n]);
src.outputs.push_back(oe);
}
++i;
//paste real transaction to the random index
auto it_to_replace = std::find_if(src.outputs.begin(), src.outputs.end(), [&](const tx_output_entry& a)
{
// HERE BE DRAGONS!!!
// SRCG: ring tweak to indexed per asset_type - DO NOT COMMIT UNTIL IT IS ALL WORKING
//return a.first == td.m_global_output_index;
return a.first == td.m_asset_type_output_index;
// LAND AHOY!!!
});
THROW_WALLET_EXCEPTION_IF(it_to_replace == src.outputs.end(), error::wallet_internal_error,
"real output not found");
tx_output_entry real_oe;
// HERE BE DRAGONS!!!
// SRCG: ring tweak to indexed per asset_type - DO NOT COMMIT UNTIL IT IS ALL WORKING
//real_oe.first = td.m_global_output_index;
real_oe.first = td.m_asset_type_output_index;
// LAND AHOY!!!
real_oe.second.dest = rct::pk2rct(td.get_public_key());
real_oe.second.mask = rct::commit(td.amount(), td.m_mask);
*it_to_replace = real_oe;
src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index);
src.real_out_additional_tx_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
src.real_output = it_to_replace - src.outputs.begin();
src.real_output_in_tx_index = td.m_internal_output_index;
src.first_rct_key_image = boost::get<cryptonote::txin_to_key>(td.m_tx.vin[0]).k_image;
src.mask = td.m_mask;
src.address_spend_pubkey = td.m_recovered_spend_pubkey;
if (false) // w.m_multisig // TODO:
// note: multisig_kLRki is a legacy struct, currently only used as a key image shuttle into the multisig tx builder
src.multisig_kLRki = {.k = {}, .L = {}, .R = {}, .ki = rct::ki2rct(td.m_key_image)};
else
src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});
detail::print_source_entry(src);
++out_index;
}
LOG_PRINT_L2("outputs prepared");
return sources;
}
//-------------------------------------------------------------------------------------------------------------------
cryptonote::transaction finalize_all_proofs_from_transfer_details(
const carrot::CarrotTransactionProposalV1 &tx_proposal,
const std::vector<std::size_t> &selected_transfers,
const cryptonote::transaction_type tx_type,
const wallet2 &w)
{
@@ -765,13 +787,13 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details(
carrot::get_output_enote_proposals(tx_proposal.normal_payment_proposals,
selfsend_payment_proposal_cores,
tx_proposal.dummy_encrypted_payment_id,
&w.get_carrot_account().s_view_balance_dev,
nullptr,
&addr_dev,
tx_proposal.key_images_sorted.at(0),
output_enote_proposals,
encrypted_payment_id,
nullptr,
change_index);
change_index,
nullptr);
CHECK_AND_ASSERT_THROW_MES(output_enote_proposals.size() == n_outputs,
"finalize_all_proofs_from_transfer_details: unexpected number of output enote proposals");
@@ -797,13 +819,17 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details(
// serialize transaction
cryptonote::transaction tx = carrot::store_carrot_to_transaction_v1(enotes,
tx_proposal.key_images_sorted,
tx_proposal.sources,
tx_proposal.fee,
encrypted_payment_id);
tx.source_asset_type = "SAL1";
tx.destination_asset_type = "SAL1";
tx.type = tx_type;
// collect input key images and amounts
// aliases
hw::device &hwdev = acc_keys.get_device();
std::vector<cryptonote::tx_source_entry> sources = get_sources(transfers, selected_transfers, "SAL1", w);
const auto &sources = tx_proposal.sources;
// inputs
uint64_t amount_in = 0;
rct::carrot_ctkeyV inSk;
@@ -857,7 +883,12 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details(
const size_t ephemeral_pubkey_index = shared_ephemeral_pubkey ? 0 : sources[i].real_output_in_tx_index;
// input_context
const carrot::input_context_t input_context = carrot::make_carrot_input_context(sources[i].first_rct_key_image);
carrot::input_context_t input_context;
if (sources[i].coinbase) {
input_context = carrot::make_carrot_input_context_coinbase(sources[i].block_index);
} else {
input_context = carrot::make_carrot_input_context(sources[i].first_rct_key_image);
}
// s^ctx_sr = H_32(s_sr, D_e, input_context)
make_carrot_sender_receiver_secret(s_sender_receiver_unctx.data,
@@ -992,15 +1023,17 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details(
// fee
uint64_t fee = amount_in - amount_out - tx.amount_burnt;
rct::BulletproofPlus bpp;
bpp = rct::bulletproof_plus_PROVE(outamounts, output_amount_blinding_factors);
// bpp
tx.rct_signatures.p.bulletproofs_plus.push_back(
rct::bulletproof_plus_PROVE(outamounts, output_amount_blinding_factors)
);
// store proofs
crypto::hash tx_prefix_hash;
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
rct::salvium_data_t salvium_data;
salvium_data.salvium_data_type = rct::SalviumOne;
tx.rct_signatures = rct::genRctSimpleCarrot(
rct::genRctSimpleCarrot(
rct::hash2rct(tx_prefix_hash),
inSk,
destinations,
@@ -1021,7 +1054,8 @@ cryptonote::transaction finalize_all_proofs_from_transfer_details(
salvium_data,
rct::sk2rct(change_x),
rct::sk2rct(change_y),
change_index
change_index,
tx.rct_signatures
);
tx.pruned = false;
@@ -1170,7 +1204,6 @@ wallet2::pending_tx finalize_all_proofs_from_transfer_details_as_pending_tx(
ptx.tx = finalize_all_proofs_from_transfer_details(
tx_proposal,
ptx.selected_transfers,
cryptonote::transaction_type::TRANSFER, // TODO:take this as a parameter
w
);
+4 -5
View File
@@ -58,15 +58,13 @@ carrot::select_inputs_func_t make_wallet2_single_transfer_input_selector(
std::set<size_t> &selected_transfer_indices_out);
std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposals_wallet2_transfer(
const wallet2::transfer_container &transfers,
const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> &subaddress_map,
wallet2 &w,
std::vector<cryptonote::tx_destination_entry> dsts,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
const uint32_t subaddr_account,
const std::set<uint32_t> &subaddr_indices,
const rct::xmr_amount ignore_above,
const rct::xmr_amount ignore_below,
wallet2::unique_index_container subtract_fee_from_outputs,
const std::uint64_t top_block_index);
std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposals_wallet2_transfer(
@@ -86,6 +84,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
const bool is_subaddress,
const size_t n_dests_per_tx,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
const std::uint64_t top_block_index);
std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposals_wallet2_sweep(
@@ -105,6 +104,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
const bool is_subaddress,
const size_t n_dests_per_tx,
const rct::xmr_amount fee_per_weight,
const rct::xmr_amount fee_quantization_mask,
const std::vector<uint8_t> &extra,
const std::uint32_t subaddr_account,
const std::set<uint32_t> &subaddr_indices,
@@ -126,7 +126,6 @@ wallet2::pending_tx make_pending_carrot_tx(const carrot::CarrotTransactionPropos
cryptonote::transaction finalize_all_proofs_from_transfer_details(
const carrot::CarrotTransactionProposalV1 &tx_proposal,
const std::vector<std::size_t> &selected_transfers,
const cryptonote::transaction_type tx_type,
const wallet2 &w);
+1 -1
View File
@@ -2035,6 +2035,7 @@ private:
public:
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, bool rct, std::unordered_set<crypto::public_key> &valid_public_keys_cache);
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, std::vector<uint64_t> &rct_offsets, std::unordered_set<crypto::public_key> &valid_public_keys_cache, uint64_t &num_spendable_global_outs, uint64_t &num_outs);
size_t get_transfer_details(const crypto::key_image &ki) const;
private:
bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked, std::unordered_set<crypto::public_key> &valid_public_keys_cache) const;
bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
@@ -2054,7 +2055,6 @@ private:
const crypto::chacha_key get_cache_key();
void verify_password_with_cached_key(const epee::wipeable_string &password);
void verify_password_with_cached_key(const crypto::chacha_key &key);
size_t get_transfer_details(const crypto::key_image &ki) const;
tx_entry_data get_tx_entries(const std::unordered_set<crypto::hash> &txids);
void sort_scan_tx_entries(std::vector<process_tx_entry_t> &unsorted_tx_entries);
void process_scan_txs(const tx_entry_data &txs_to_scan, const tx_entry_data &txs_to_reprocess, const std::unordered_set<crypto::hash> &tx_hashes_to_reprocess, detached_blockchain_data &dbd);