Skip to content

Commit

Permalink
successful construct and scan for carrot
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffro256 committed Jul 16, 2024
1 parent 4622286 commit 1e41c11
Show file tree
Hide file tree
Showing 16 changed files with 336 additions and 128 deletions.
101 changes: 86 additions & 15 deletions src/seraphis_core/carrot_payment_proposal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
#include "carrot_payment_proposal.h"

//local headers
#include "jamtis_account_secrets.h"
#include "jamtis_enote_utils.h"
#include "ringct/rctOps.h"
#include "seraphis_crypto/sp_crypto_utils.h"

//third party headers

Expand Down Expand Up @@ -76,20 +78,21 @@ static crypto::secret_key get_enote_ephemeal_privkey(const CarrotPaymentProposal
static void get_output_proposal_plain_root_secrets_and_ephem_pubkey(const CarrotPaymentProposalV1 &proposal,
const rct::key &input_context,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out,
rct::key &x_all_out,
crypto::public_key &x_all_out,
rct::key &q_out)
{
// 1. enote ephemeral pubkey: D_e = ed_to_x(k_e K_base)
get_enote_ephemeral_pubkey(proposal, enote_ephemeral_pubkey_out);

// 2. X_fa = X_ir = X_ur = 8 * k_e * K^j_v
x_all_out = rct::scalarmultKey(rct::scalarmult8(rct::pk2rct(proposal.destination.m_view_public_key)),
rct::sk2rct(get_enote_ephemeal_privkey(proposal)));
x_all_out = rct::rct2pk(rct::scalarmultKey(rct::scalarmult8(rct::pk2rct(proposal.destination.m_view_public_key)),
rct::sk2rct(get_enote_ephemeal_privkey(proposal))));
normalize_x(x_all_out);

// 5. q = H_32(X_fa, X_ir, X_ur, D_e, input_context)
make_jamtis_sender_receiver_secret(x_all_out.bytes,
x_all_out.bytes,
x_all_out.bytes,
make_jamtis_sender_receiver_secret(to_bytes(x_all_out),
to_bytes(x_all_out),
to_bytes(x_all_out),
enote_ephemeral_pubkey_out,
input_context,
q_out);
Expand All @@ -98,20 +101,21 @@ static void get_output_proposal_plain_root_secrets_and_ephem_pubkey(const Carrot
//-------------------------------------------------------------------------------------------------------------------
static void get_output_proposal_address_parts_v1(const rct::key &q,
const secret256_ptr_t x_all,
const CarrotPaymentProposalV1 &output_destination,
const crypto::public_key &destination_spend_pubkey,
const carrot_randomness_t &randomness,
const rct::key &amount_commitment,
rct::key &onetime_address_out,
carrot_encrypted_randomness_t &randomness_enc_out,
view_tag_t &view_tag_out)
{
// 1. onetime address: Ko = ... + K^j_s
make_jamtis_onetime_address_rct(rct::pk2rct(output_destination.destination.m_spend_public_key),
make_jamtis_onetime_address_rct(rct::pk2rct(destination_spend_pubkey),
q,
amount_commitment,
onetime_address_out);

// 2. encrypt address tag: addr_tag_enc = addr_tag XOR H_16(X_fa, X_ir, Ko)
randomness_enc_out = encrypt_jamtis_address_tag(output_destination.randomness,
randomness_enc_out = encrypt_jamtis_address_tag(randomness,
x_all,
x_all,
onetime_address_out);
Expand All @@ -134,6 +138,13 @@ bool operator==(const CarrotPaymentProposalV1 &a, const CarrotPaymentProposalV1
a.partial_memo == b.partial_memo;
}
//-------------------------------------------------------------------------------------------------------------------
bool operator==(const CarrotPaymentProposalChangeV1 &a, const CarrotPaymentProposalChangeV1 &b)
{
return a.amount == b.amount &&
a.enote_ephemeral_pubkey == b.enote_ephemeral_pubkey &&
a.partial_memo == b.partial_memo;
}
//-------------------------------------------------------------------------------------------------------------------
void get_enote_ephemeral_pubkey(const CarrotPaymentProposalV1 &proposal,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out)
{
Expand Down Expand Up @@ -174,15 +185,16 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal,
make_jamtis_input_context_coinbase(block_height, input_context);

// 3. plain enote ephemeral pubkey and root secrets: D_e, X_fa, X_ir, q
rct::key x_all; auto dhe_wiper = auto_wiper(x_all);
crypto::public_key x_all; auto dhe_wiper = auto_wiper(x_all);
rct::key q; auto q_wiper = auto_wiper(q);
get_output_proposal_plain_root_secrets_and_ephem_pubkey(proposal,
input_context, enote_ephemeral_pubkey_out, x_all, q);

// 4. build the output enote address pieces
get_output_proposal_address_parts_v1(q,
x_all.bytes,
proposal,
to_bytes(x_all),
proposal.destination.m_spend_public_key,
proposal.randomness,
rct::commit(proposal.amount, rct::I),
output_enote_core_out.onetime_address,
addr_tag_enc_out,
Expand All @@ -207,7 +219,7 @@ void get_output_proposal_v1(const CarrotPaymentProposalV1 &proposal,
"jamtis payment proposal: invalid enote ephemeral privkey randomness (zero).");

// 2. plain enote ephemeral pubkey and root secrets: D_e, X_fa, X_ir, q
rct::key x_all; auto dhe1_wiper = auto_wiper(x_all);
crypto::public_key x_all; auto dhe1_wiper = auto_wiper(x_all);
rct::key q; auto q_wiper = auto_wiper(q);
get_output_proposal_plain_root_secrets_and_ephem_pubkey(proposal,
input_context, enote_ephemeral_pubkey_out, x_all, q);
Expand All @@ -217,8 +229,9 @@ void get_output_proposal_v1(const CarrotPaymentProposalV1 &proposal,

// 4. build the output enote address pieces
get_output_proposal_address_parts_v1(q,
x_all.bytes,
proposal,
to_bytes(x_all),
proposal.destination.m_spend_public_key,
proposal.randomness,
rct::commit(proposal.amount, rct::sk2rct(output_proposal_core_out.amount_blinding_factor)),
output_proposal_core_out.onetime_address,
addr_tag_enc_out,
Expand All @@ -232,6 +245,64 @@ void get_output_proposal_v1(const CarrotPaymentProposalV1 &proposal,
partial_memo_out = proposal.partial_memo;
}
//-------------------------------------------------------------------------------------------------------------------
void get_output_proposal_v1(const CarrotPaymentProposalChangeV1 &proposal,
const crypto::secret_key &k_view,
const crypto::public_key &primary_address_spend_pubkey,
const rct::key &input_context,
SpOutputProposalCore &output_proposal_core_out,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out,
encrypted_amount_t &encrypted_amount_out,
encrypted_address_tag_t &addr_tag_enc_out,
view_tag_t &view_tag_out,
TxExtra &partial_memo_out)
{
// 1. X_fa = X_ir = X_ur = NormalizeX(8 * k_v * ConvertPubkey1(D_e))
crypto::public_key x_all;
CHECK_AND_ASSERT_THROW_MES(make_carrot_x_all_recipient(k_view,
proposal.enote_ephemeral_pubkey,
x_all), "get output proposal v1: carrot enote ephemeral pubkey failed to deserialize");

// 2. q = H_32(X_fa, X_ir, X_ur, D_e, input_context)
rct::key sender_receiver_secret;
make_jamtis_sender_receiver_secret(to_bytes(x_all),
to_bytes(x_all),
to_bytes(x_all),
proposal.enote_ephemeral_pubkey,
input_context,
sender_receiver_secret);

// 3. amount blinding factor: y = Hn(q, enote_type)
make_jamtis_amount_blinding_factor(sender_receiver_secret,
JamtisEnoteType::PLAIN,
output_proposal_core_out.amount_blinding_factor);

// 4. make secret change destination
crypto::public_key secret_change_spend_pubkey;
make_carrot_secret_change_spend_pubkey(primary_address_spend_pubkey,
k_view,
secret_change_spend_pubkey);

// 5. build the output enote address pieces
get_output_proposal_address_parts_v1(sender_receiver_secret,
to_bytes(x_all),
secret_change_spend_pubkey,
gen_address_tag(),
rct::commit(proposal.amount, rct::sk2rct(output_proposal_core_out.amount_blinding_factor)),
output_proposal_core_out.onetime_address,
addr_tag_enc_out,
view_tag_out);

// 6. make encryped amount
encrypted_amount_out = encrypt_jamtis_amount(proposal.amount,
sender_receiver_secret,
output_proposal_core_out.onetime_address);

// 7. save the amount, enote ephemeral pubkey, and partial memo
output_proposal_core_out.amount = proposal.amount;
enote_ephemeral_pubkey_out = proposal.enote_ephemeral_pubkey;
partial_memo_out = proposal.partial_memo;
}
//-------------------------------------------------------------------------------------------------------------------
CarrotPaymentProposalV1 gen_carrot_payment_proposal_v1(const bool is_subaddress,
const bool has_payment_id,
const rct::xmr_amount amount,
Expand Down
42 changes: 41 additions & 1 deletion src/seraphis_core/carrot_payment_proposal.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,26 @@ struct CarrotPaymentProposalV1 final
TxExtra partial_memo;
};

////
// CarrotPaymentProposaChangelV1
// - for creating an output proposal to send an change to yourself
///
struct CarrotPaymentProposalChangeV1 final
{
/// b
rct::xmr_amount amount;

/// enote ephemeral pubkey: xr G
crypto::x25519_pubkey enote_ephemeral_pubkey;

/// memo elements to add to the tx memo
TxExtra partial_memo;
};

/// equality operators
bool operator==(const CarrotPaymentProposalV1 &a, const CarrotPaymentProposalV1 &b);
/// equality operators
bool operator==(const CarrotPaymentProposalChangeV1 &a, const CarrotPaymentProposalChangeV1 &b);

/**
* brief: get_enote_ephemeral_pubkey - get the proposal's enote ephemeral pubkey D_e
Expand All @@ -80,7 +98,6 @@ bool operator==(const CarrotPaymentProposalV1 &a, const CarrotPaymentProposalV1
*/
void get_enote_ephemeral_pubkey(const CarrotPaymentProposalV1 &proposal,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out);

/**
* brief: get_coinbase_output_proposal_v1 - convert the jamtis proposal to a coinbase output proposal
* param: proposal -
Expand Down Expand Up @@ -118,6 +135,29 @@ void get_output_proposal_v1(const CarrotPaymentProposalV1 &proposal,
view_tag_t &view_tag_out,
TxExtra &partial_memo_out);
/**
* brief: get_output_proposal_v1 - convert the jamtis proposal to an output proposal
* param: proposal -
* param: k_view -
* param: primary_address_spend_pubkey -
* param: input_context -
* outparam: output_proposal_core_out -
* outparam: enote_ephemeral_pubkey_out -
* outparam: encrypted_amount_out -
* outparam: addr_tag_enc_out -
* outparam: view_tag_out -
* outparam: partial_memo_out -
*/
void get_output_proposal_v1(const CarrotPaymentProposalChangeV1 &proposal,
const crypto::secret_key &k_view,
const crypto::public_key &primary_address_spend_pubkey,
const rct::key &input_context,
SpOutputProposalCore &output_proposal_core_out,
crypto::x25519_pubkey &enote_ephemeral_pubkey_out,
encrypted_amount_t &encrypted_amount_out,
encrypted_address_tag_t &addr_tag_enc_out,
view_tag_t &view_tag_out,
TxExtra &partial_memo_out);
/**
* brief: gen_jamtis_payment_proposal_v1 - generate a random proposal
* param: is_subaddress - whether to generate a prooposal to subaddress
* param: has_payment_id - true to generate non-zero payment ID, false for null payment ID
Expand Down
35 changes: 34 additions & 1 deletion src/seraphis_core/jamtis_account_secrets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,41 @@ void make_carrot_secret_change_spend_extension_g(const crypto::secret_key &k_vie
crypto::secret_key &k_secret_change_spend_extension_g_out)
{
// k^change_g = H_n[k_v]("G")

SpKDFTranscript transcript{config::HASH_KEY_CARROT_CHANGE_SPEND_EXTENSION_G, 0};
sp_derive_key(to_bytes(k_view),
transcript.data(),
transcript.size(),
to_bytes(k_secret_change_spend_extension_g_out));
}
//-------------------------------------------------------------------------------------------------------------------
void make_carrot_secret_change_spend_extension_u(const crypto::secret_key &k_view,
crypto::secret_key &k_secret_change_spend_extension_u_out)
{
// k^change_u = H_n[k_v]("U")
SpKDFTranscript transcript{config::HASH_KEY_CARROT_CHANGE_SPEND_EXTENSION_U, 0};
sp_derive_key(to_bytes(k_view),
transcript.data(),
transcript.size(),
to_bytes(k_secret_change_spend_extension_u_out));
}
//-------------------------------------------------------------------------------------------------------------------
void make_carrot_secret_change_spend_pubkey(const crypto::public_key &primary_address_spend_pubkey,
const crypto::secret_key &k_view,
crypto::public_key &secret_change_spend_pubkey_out)
{
// k^change_g = H_n[k_v]("G")
crypto::secret_key k_secret_change_spend_extension_g;
make_carrot_secret_change_spend_extension_g(k_view,
k_secret_change_spend_extension_g);

// k^change_u = H_n[k_v]("U")
crypto::secret_key k_secret_change_spend_extension_u;
make_carrot_secret_change_spend_extension_u(k_view,
k_secret_change_spend_extension_u);

// K^change_s = K_s + k^change_g G + k^change_u U
mask_key(k_secret_change_spend_extension_g, primary_address_spend_pubkey, secret_change_spend_pubkey_out);
extend_seraphis_spendkey_u(k_secret_change_spend_extension_u, secret_change_spend_pubkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
} //namespace jamtis
Expand Down
18 changes: 18 additions & 0 deletions src/seraphis_core/jamtis_account_secrets.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,23 @@ void make_rct_spendkey(const crypto::secret_key &k_generate_image,
*/
void make_carrot_secret_change_spend_extension_g(const crypto::secret_key &k_view,
crypto::secret_key &k_secret_change_spend_extension_g_out);
/**
* brief: make_carrot_secret_change_spend_extension_u - spend pubkey extension for Janus-protected change (U)
* k^change_u = H_n[k_v]("U")
* param: k_view - k_v
* outparam: k_secret_change_spend_extension_g_out - k^change_u
*/
void make_carrot_secret_change_spend_extension_u(const crypto::secret_key &k_view,
crypto::secret_key &k_secret_change_spend_extension_u_out);
/**
* brief: make_carrot_secret_change_spend_pubkey - carrot spend pubkey for Janus-protected change
* K^change_s = K_s + k^change_g G + k^change_u U
* param: primary_address_spend_pubkey - K_s
* param: k_view - k_v
* outparam: secret_change_spend_pubkey_out - K^change_s
*/
void make_carrot_secret_change_spend_pubkey(const crypto::public_key &primary_address_spend_pubkey,
const crypto::secret_key &k_view,
crypto::public_key &secret_change_spend_pubkey_out);
} //namespace jamtis
} //namespace sp
32 changes: 30 additions & 2 deletions src/seraphis_core/jamtis_enote_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,32 @@ void make_carrot_enote_ephemeral_privkey(const carrot_randomness_t &n,
assert(transcript.size() < 128); // for performance (should be 1 block size transcript)
}
//-------------------------------------------------------------------------------------------------------------------
bool make_carrot_x_all_recipient(const crypto::secret_key &k_view,
const crypto::x25519_pubkey &enote_ephemeral_pubkey,
crypto::public_key &x_all_out)
{
// @TODO: this is slow as hell, replace with accelerated SUPERCOP impl
// @TODO: HW device support

ge_p3 p3;
if (0 != ge_fromx25519_vartime(&p3, enote_ephemeral_pubkey.data)) // K_e
return false;

ge_p2 p2;
ge_scalarmult(&p2, to_bytes(k_view), &p3); // k_v K_e

ge_p1p1 p1p1;
ge_mul8(&p1p1, &p2); // 8 k_v K_e

ge_p1p1_to_p2(&p2, &p1p1);

ge_tobytes(to_bytes(x_all_out), &p2);

normalize_x(x_all_out);

return true;
}
//-------------------------------------------------------------------------------------------------------------------
void make_jamtis_view_tag(const secret256_ptr_t x_fa,
const secret256_ptr_t x_ir,
const rct::key &onetime_address,
Expand Down Expand Up @@ -509,7 +535,7 @@ void recover_recipient_address_spend_key_sp(const rct::key &sender_receiver_secr
void recover_recipient_address_spend_key_rct(const rct::key &sender_receiver_secret,
const rct::key &amount_commitment,
const rct::key &onetime_address,
rct::key &recipient_address_spend_key_out)
crypto::public_key &recipient_address_spend_key_out)
{
// K^o_ext = k^o_g G + k^o_u U
rct::key sender_extension_pubkey;
Expand All @@ -518,7 +544,9 @@ void recover_recipient_address_spend_key_rct(const rct::key &sender_receiver_sec
sender_extension_pubkey);

// K^j_s = Ko - K^o_ext
rct::subKeys(recipient_address_spend_key_out, onetime_address, sender_extension_pubkey);
rct::key recipient_address_spend_key_rct;
rct::subKeys(recipient_address_spend_key_rct, onetime_address, sender_extension_pubkey);
recipient_address_spend_key_out = rct::rct2pk(recipient_address_spend_key_rct);
}
//-------------------------------------------------------------------------------------------------------------------
bool test_jamtis_onetime_address_sp(const rct::key &recipient_address_spend_key,
Expand Down
Loading

0 comments on commit 1e41c11

Please sign in to comment.