Skip to content

Commit b70222c

Browse files
committed
get_output_enote_proposals now supports external selfsends
1 parent 8dc6a12 commit b70222c

File tree

5 files changed

+101
-30
lines changed

5 files changed

+101
-30
lines changed

src/carrot_core/output_set_finalization.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ tools::optional_variant<CarrotPaymentProposalV1, CarrotPaymentProposalSelfSendV1
146146
//-------------------------------------------------------------------------------------------------------------------
147147
void get_output_enote_proposals(std::vector<CarrotPaymentProposalV1> &&normal_payment_proposals,
148148
std::vector<CarrotPaymentProposalSelfSendV1> &&selfsend_payment_proposals,
149-
const view_balance_secret_device &s_view_balance_dev,
149+
const view_balance_secret_device *s_view_balance_dev,
150+
const view_incoming_key_device *k_view_dev,
151+
const crypto::public_key &account_spend_pubkey,
150152
const crypto::key_image &tx_first_key_image,
151153
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
152154
encrypted_payment_id_t &encrypted_payment_id_out)
@@ -208,18 +210,34 @@ void get_output_enote_proposals(std::vector<CarrotPaymentProposalV1> &&normal_pa
208210
encrypted_payment_id_out = encrypted_payment_id;
209211
}
210212

211-
// in the case that the pid is ambiguous, set it to random bytes
213+
// in the case that the pid target is ambiguous, set it to random bytes
212214
const bool ambiguous_pid_destination = num_integrated == 0 && normal_payment_proposals.size() > 1;
213215
if (ambiguous_pid_destination)
214216
encrypted_payment_id_out = gen_payment_id();
215217

216-
// construct selfsend enotes
218+
// construct selfsend enotes, preferring internal enotes over special enotes when possible
217219
for (const CarrotPaymentProposalSelfSendV1 &selfsend_payment_proposal : selfsend_payment_proposals)
218220
{
219-
get_output_proposal_internal_v1(selfsend_payment_proposal,
220-
s_view_balance_dev,
221-
tx_first_key_image,
222-
tools::add_element(output_enote_proposals_out));
221+
if (s_view_balance_dev != nullptr)
222+
{
223+
get_output_proposal_internal_v1(selfsend_payment_proposal,
224+
*s_view_balance_dev,
225+
tx_first_key_image,
226+
tools::add_element(output_enote_proposals_out));
227+
}
228+
else if (k_view_dev != nullptr)
229+
{
230+
get_output_proposal_special_v1(selfsend_payment_proposal,
231+
*k_view_dev,
232+
account_spend_pubkey,
233+
tx_first_key_image,
234+
tools::add_element(output_enote_proposals_out));
235+
}
236+
else // neither k_v nor s_vb device passed
237+
{
238+
ASSERT_MES_AND_THROW(
239+
"get output enote proposals: neither a view-balance nor view-incoming device was provided");
240+
}
223241
}
224242

225243
// sort enotes by D_e and assert uniqueness properties of D_e

src/carrot_core/output_set_finalization.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,25 @@ tools::optional_variant<CarrotPaymentProposalV1, CarrotPaymentProposalSelfSendV1
8787
const crypto::public_key &change_address_spend_pubkey,
8888
const crypto::x25519_pubkey &other_enote_ephemeral_pubkey);
8989
/**
90-
* brief: get_output_enote_proposals - convert payment proposals into output enote proposals
90+
* brief: get_output_enote_proposals - convert a *finalized* set of payment proposals into output enote proposals
91+
* param: normal_payment_proposals -
92+
* param: selfsend_payment_proposals -
93+
* param: s_view_balance_dev - pointer to view-balance device (OPTIONAL)
94+
* param: k_view_dev - pointer to view-incoming device (OPTIONAL)
95+
* param: account_spend_pubkey - K_s
96+
* param: tx_first_key_image - KI_1
97+
* outparam: output_enote_proposals_out -
98+
* outparam: encrypted_payment_id_out - pid_enc
99+
* throw: std::runtime_error if the payment proposals do not represent a valid tx output set, or if no devices
100+
*
101+
* If s_view_balance_dev is not NULL, then the selfsend payments are converted into *internal* enotes.
102+
* Otherwise, if k_view_dev is not NULL, then the selfsend payments are converted into *external* enotes.
91103
*/
92104
void get_output_enote_proposals(std::vector<CarrotPaymentProposalV1> &&normal_payment_proposals,
93105
std::vector<CarrotPaymentProposalSelfSendV1> &&selfsend_payment_proposals,
94-
const view_balance_secret_device &s_view_balance_dev,
106+
const view_balance_secret_device *s_view_balance_dev,
107+
const view_incoming_key_device *k_view_dev,
108+
const crypto::public_key &account_spend_pubkey,
95109
const crypto::key_image &tx_first_key_image,
96110
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
97111
encrypted_payment_id_t &encrypted_payment_id_out);

src/carrot_core/payment_proposal.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal,
321321
//-------------------------------------------------------------------------------------------------------------------
322322
void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &proposal,
323323
const view_incoming_key_device &k_view_dev,
324-
const crypto::public_key &primary_address_spend_pubkey,
324+
const crypto::public_key &account_spend_pubkey,
325325
const crypto::key_image &tx_first_key_image,
326326
RCTOutputEnoteProposal &output_enote_out)
327327
{
@@ -362,7 +362,7 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo
362362
k_view_dev.make_janus_anchor_special(proposal.enote_ephemeral_pubkey,
363363
input_context,
364364
output_enote_out.enote.onetime_address,
365-
primary_address_spend_pubkey,
365+
account_spend_pubkey,
366366
janus_anchor_special);
367367

368368
// 6. encrypt special anchor: anchor_enc = anchor XOR m_anchor

src/carrot_core/payment_proposal.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,20 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal,
129129
* brief: get_output_proposal_v1 - convert the carrot proposal to an output proposal (external selfsend)
130130
* param: proposal -
131131
* param: k_view_dev -
132-
* param: primary_address_spend_pubkey -
132+
* param: account_spend_pubkey -
133133
* param: tx_first_key_image -
134134
* outparam: output_enote_out -
135135
*/
136136
void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &proposal,
137137
const view_incoming_key_device &k_view_dev,
138-
const crypto::public_key &primary_address_spend_pubkey,
138+
const crypto::public_key &account_spend_pubkey,
139139
const crypto::key_image &tx_first_key_image,
140140
RCTOutputEnoteProposal &output_enote_out);
141141
/**
142142
* brief: get_output_proposal_internal_v1 - convert the carrot proposal to an output proposal (internal)
143143
* param: proposal -
144144
* param: s_view_balance_dev -
145-
* param: primary_address_spend_pubkey -
145+
* param: account_spend_pubkey -
146146
* param: tx_first_key_image -
147147
* outparam: output_enote_out -
148148
* outparam: partial_memo_out -

tests/unit_tests/carrot_core.cpp

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -893,10 +893,11 @@ TEST(carrot_core, main_address_coinbase_scan_completeness)
893893
enote.onetime_address));
894894
}
895895
//----------------------------------------------------------------------------------------------------------------------
896-
static void subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(const bool alice_subaddress,
896+
static void subtest_2out_transfer_get_output_enote_proposals_completeness(const bool alice_subaddress,
897897
const bool bob_subaddress,
898898
const bool bob_integrated,
899-
const CarrotEnoteType alice_selfsend_type)
899+
const CarrotEnoteType alice_selfsend_type,
900+
const bool alice_internal_selfsends)
900901
{
901902
// generate alice keys and address
902903
const mock_carrot_keys alice = mock_carrot_keys::generate();
@@ -972,11 +973,13 @@ static void subtest_2out_transfer_get_enote_output_proposals_internal_ss_complet
972973
encrypted_payment_id_t encrypted_payment_id;
973974
get_output_enote_proposals({bob_payment_proposal},
974975
{alice_payment_proposal},
975-
alice.s_view_balance_dev,
976+
alice_internal_selfsends ? &alice.s_view_balance_dev : nullptr,
977+
&alice.k_view_dev,
978+
alice.account_spend_pubkey,
976979
tx_first_key_image,
977980
enote_proposals,
978981
encrypted_payment_id);
979-
982+
980983
ASSERT_EQ(2, enote_proposals.size()); // 2-out tx
981984

982985
// collect enotes
@@ -1061,37 +1064,73 @@ static void subtest_2out_transfer_get_enote_output_proposals_internal_ss_complet
10611064
//----------------------------------------------------------------------------------------------------------------------
10621065
TEST(carrot_core, get_enote_output_proposals_internal_ss_main2main_completeness)
10631066
{
1064-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(false, false, false, CarrotEnoteType::PAYMENT);
1065-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(false, false, false, CarrotEnoteType::CHANGE);
1067+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, false, CarrotEnoteType::PAYMENT, true);
1068+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, false, CarrotEnoteType::CHANGE, true);
10661069
}
10671070
//----------------------------------------------------------------------------------------------------------------------
10681071
TEST(carrot_core, get_enote_output_proposals_internal_ss_main2sub_completeness)
10691072
{
1070-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(false, true, false, CarrotEnoteType::PAYMENT);
1071-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(false, true, false, CarrotEnoteType::CHANGE);
1073+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, true, false, CarrotEnoteType::PAYMENT, true);
1074+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, true, false, CarrotEnoteType::CHANGE, true);
10721075
}
10731076
//----------------------------------------------------------------------------------------------------------------------
10741077
TEST(carrot_core, get_enote_output_proposals_internal_ss_main2integ_completeness)
10751078
{
1076-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(false, false, true, CarrotEnoteType::PAYMENT);
1077-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(false, false, true, CarrotEnoteType::CHANGE);
1079+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, true, CarrotEnoteType::PAYMENT, true);
1080+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, true, CarrotEnoteType::CHANGE, true);
10781081
}
10791082
//----------------------------------------------------------------------------------------------------------------------
10801083
TEST(carrot_core, get_enote_output_proposals_internal_ss_sub2main_completeness)
10811084
{
1082-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(true, false, false, CarrotEnoteType::PAYMENT);
1083-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(true, false, false, CarrotEnoteType::CHANGE);
1085+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, false, CarrotEnoteType::PAYMENT, true);
1086+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, false, CarrotEnoteType::CHANGE, true);
10841087
}
10851088
//----------------------------------------------------------------------------------------------------------------------
10861089
TEST(carrot_core, get_enote_output_proposals_internal_ss_sub2sub_completeness)
10871090
{
1088-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(true, true, false, CarrotEnoteType::PAYMENT);
1089-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(true, true, false, CarrotEnoteType::CHANGE);
1091+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, true, false, CarrotEnoteType::PAYMENT, true);
1092+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, true, false, CarrotEnoteType::CHANGE, true);
10901093
}
10911094
//----------------------------------------------------------------------------------------------------------------------
10921095
TEST(carrot_core, get_enote_output_proposals_internal_ss_sub2integ_completeness)
10931096
{
1094-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(true, false, true, CarrotEnoteType::PAYMENT);
1095-
subtest_2out_transfer_get_enote_output_proposals_internal_ss_completeness(true, false, true, CarrotEnoteType::CHANGE);
1097+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, true, CarrotEnoteType::PAYMENT, true);
1098+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, true, CarrotEnoteType::CHANGE, true);
1099+
}
1100+
//----------------------------------------------------------------------------------------------------------------------
1101+
TEST(carrot_core, get_enote_output_proposals_external_ss_main2main_completeness)
1102+
{
1103+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, false, CarrotEnoteType::PAYMENT, false);
1104+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, false, CarrotEnoteType::CHANGE, false);
1105+
}
1106+
//----------------------------------------------------------------------------------------------------------------------
1107+
TEST(carrot_core, get_enote_output_proposals_external_ss_main2sub_completeness)
1108+
{
1109+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, true, false, CarrotEnoteType::PAYMENT, false);
1110+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, true, false, CarrotEnoteType::CHANGE, false);
1111+
}
1112+
//----------------------------------------------------------------------------------------------------------------------
1113+
TEST(carrot_core, get_enote_output_proposals_external_ss_main2integ_completeness)
1114+
{
1115+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, true, CarrotEnoteType::PAYMENT, false);
1116+
subtest_2out_transfer_get_output_enote_proposals_completeness(false, false, true, CarrotEnoteType::CHANGE, false);
1117+
}
1118+
//----------------------------------------------------------------------------------------------------------------------
1119+
TEST(carrot_core, get_enote_output_proposals_external_ss_sub2main_completeness)
1120+
{
1121+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, false, CarrotEnoteType::PAYMENT, false);
1122+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, false, CarrotEnoteType::CHANGE, false);
1123+
}
1124+
//----------------------------------------------------------------------------------------------------------------------
1125+
TEST(carrot_core, get_enote_output_proposals_external_ss_sub2sub_completeness)
1126+
{
1127+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, true, false, CarrotEnoteType::PAYMENT, false);
1128+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, true, false, CarrotEnoteType::CHANGE, false);
1129+
}
1130+
//----------------------------------------------------------------------------------------------------------------------
1131+
TEST(carrot_core, get_enote_output_proposals_external_ss_sub2integ_completeness)
1132+
{
1133+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, true, CarrotEnoteType::PAYMENT, false);
1134+
subtest_2out_transfer_get_output_enote_proposals_completeness(true, false, true, CarrotEnoteType::CHANGE, false);
10961135
}
10971136
//----------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)