Skip to content

Commit

Permalink
4-key jamtis/jamtis-rct/carrot
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffro256 committed Aug 20, 2024
1 parent 83331b6 commit afe5119
Show file tree
Hide file tree
Showing 108 changed files with 6,972 additions and 3,591 deletions.
1 change: 1 addition & 0 deletions src/crypto/crypto-ops-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,7 @@ const fe fe_fffb1 = {-31702527, -2466483, -26106795, -12203692, -12169197, -3210
const fe fe_fffb2 = {8166131, -6741800, -17040804, 3154616, 21461005, 1466302, -30876704, -6368709, 10503587, -13363080}; /* sqrt(2 * A * (A + 2)) */
const fe fe_fffb3 = {-13620103, 14639558, 4532995, 7679154, 16815101, -15883539, -22863840, -14813421, 13716513, -6477756}; /* sqrt(-sqrt(-1) * A * (A + 2)) */
const fe fe_fffb4 = {-21786234, -12173074, 21573800, 4524538, -4645904, 16204591, 8012863, -8444712, 3212926, 6885324}; /* sqrt(sqrt(-1) * A * (A + 2)) */
const fe fe_fffb5 = {-12222970, -8312128, -11511410, 9067497, -15300785, -241793, 25456130, 14121551, -12187136, 3972024}; /* sqrt(-(A + 2)) */
const ge_p3 ge_p3_identity = { {0}, {1, 0}, {1, 0}, {0} };
const ge_p3 ge_p3_H = {
{7329926, -15101362, 31411471, 7614783, 27996851, -3197071, -11157635, -6878293, 466949, -7986503},
Expand Down
119 changes: 119 additions & 0 deletions src/crypto/crypto-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2422,6 +2422,125 @@ void ge_fromfe_frombytes_vartime(ge_p2 *r, const unsigned char *s) {
#endif
}

int ge_fromx25519_vartime(ge_p3 *h, const unsigned char *s) {
fe u;
fe v;
fe vxx;
fe check;

/* From fe_frombytes.c */

int64_t h0 = load_4(s);
int64_t h1 = load_3(s + 4) << 6;
int64_t h2 = load_3(s + 7) << 5;
int64_t h3 = load_3(s + 10) << 3;
int64_t h4 = load_3(s + 13) << 2;
int64_t h5 = load_4(s + 16);
int64_t h6 = load_3(s + 20) << 7;
int64_t h7 = load_3(s + 23) << 5;
int64_t h8 = load_3(s + 26) << 4;
int64_t h9 = (load_3(s + 29) & 8388607) << 2;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;

/* Validate the number to be canonical */
if (h9 == 33554428 && h8 == 268435440 && h7 == 536870880 && h6 == 2147483520 &&
h5 == 4294967295 && h4 == 67108860 && h3 == 134217720 && h2 == 536870880 &&
h1 == 1073741760 && h0 >= 4294967277) {
return -1;
}

carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;

carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;

/* End fe_frombytes.c */

/* Start ge_fromx25519_vartime specific code */

check[0] = h0;
check[1] = h1;
check[2] = h2;
check[3] = h3;
check[4] = h4;
check[5] = h5;
check[6] = h6;
check[7] = h7;
check[8] = h8;
check[9] = h9; /* load s into `check`, where s is the X coordinate of the X25519 point */

fe_1(v); /* v = 1 */
fe_copy(u, v); /* u = 1 */
u[0] = -1; /* u = -1 */
fe_add(u, u, check); /* u = s - 1 */
fe_add(v, v, check); /* v = s + 1 */
fe_invert(v, v); /* v = 1 / (s + 1) */
fe_mul(h->Y, u, v); /* Y = (s - 1) / (s + 1) */

/* End ge_fromx25519_vartime specific code */

fe_1(h->Z);
fe_sq(u, h->Y);
fe_mul(v, u, fe_d);
fe_sub(u, u, h->Z); /* u = y^2-1 */
fe_add(v, v, h->Z); /* v = dy^2+1 */

fe_divpowm1(h->X, u, v); /* x = uv^3(uv^7)^((q-5)/8) */

fe_sq(vxx, h->X);
fe_mul(vxx, vxx, v);
fe_sub(check, vxx, u); /* vx^2-u */
if (fe_isnonzero(check)) {
fe_add(check, vxx, u); /* vx^2+u */
if (fe_isnonzero(check)) {
return -1;
}
fe_mul(h->X, h->X, fe_sqrtm1);
}

// check/negation here differs from ge_frombytes_vartime: we always force it to be positive
if (fe_isnegative(h->X)) {
fe_neg(h->X, h->X);
}

fe_mul(h->T, h->X, h->Y);
return 0;
}

void ge_p3_to_x25519(unsigned char *s, const ge_p3 *h)
{
fe x25519;
fe num;
fe denom;

fe_invert(x25519, h->Z); // `x25519`: 1 / Z
fe_mul(x25519, h->Y, x25519); // `x25519`: y = Y / Z
fe_1(num); // `num`: 1
fe_add(num, num, x25519); // `num`: 1 + y
fe_1(denom); // `denom`: 1
fe_sub(denom, denom, x25519); // `denom`: 1 - y
fe_invert(denom, denom); // `denom`: 1 / (1 - y)
fe_mul(x25519, num, denom); // `x25519`: x = (1 + y) / (1 - y)

fe_tobytes(s, x25519);
}

void sc_0(unsigned char *s) {
int i;
for (i = 0; i < 32; i++) {
Expand Down
3 changes: 3 additions & 0 deletions src/crypto/crypto-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,12 @@ extern const fe fe_fffb1;
extern const fe fe_fffb2;
extern const fe fe_fffb3;
extern const fe fe_fffb4;
extern const fe fe_fffb5; /* sqrt(-(A + 2)) */
extern const ge_p3 ge_p3_identity;
extern const ge_p3 ge_p3_H;
void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *);
int ge_fromx25519_vartime(ge_p3 *, const unsigned char *);
void ge_p3_to_x25519(unsigned char *, const ge_p3 *);
void sc_0(unsigned char *);
void sc_reduce32(unsigned char *);
void sc_add(unsigned char *, const unsigned char *, const unsigned char *);
Expand Down
12 changes: 6 additions & 6 deletions src/crypto/generators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ constexpr public_key H = bytes_to<public_key>({ 0x8b, 0x65, 0x59, 0x70, 0x15, 0x
//seraphis generator X: keccak_to_pt(keccak("seraphis_X"))
constexpr public_key X = bytes_to<public_key>({ 0xa4, 0xfb, 0x43, 0xca, 0x69, 0x5e, 0x12, 0x99, 0x88, 0x02, 0xa2, 0x0a, 0x15,
0x8f, 0x12, 0xea, 0x79, 0x47, 0x4f, 0xb9, 0x01, 0x21, 0x16, 0x95, 0x6a, 0x69, 0x76, 0x7c, 0x4d, 0x41, 0x11, 0x0f });
//seraphis generator U: keccak_to_pt(keccak("seraphis_U"))
constexpr public_key U = bytes_to<public_key>({ 0x10, 0x94, 0x8b, 0x00, 0xd2, 0xde, 0x50, 0xb5, 0x76, 0x99, 0x8c, 0x11, 0xe8,
0x3c, 0x59, 0xa7, 0x96, 0x84, 0xd2, 0x5c, 0x9f, 0x8a, 0x0d, 0xc6, 0x86, 0x45, 0x70, 0xd7, 0x97, 0xb9, 0xc1, 0x6e });
//seraphis generator U: keccak_to_pt(keccak("Monero Generator T"))
constexpr public_key U = bytes_to<public_key>({ 0x96, 0x6f, 0xc6, 0x6b, 0x82, 0xcd, 0x56, 0xcf, 0x85, 0xea, 0xec, 0x80, 0x1c,
0x42, 0x84, 0x5f, 0x5f, 0x40, 0x88, 0x78, 0xd1, 0x56, 0x1e, 0x00, 0xd3, 0xd7, 0xde, 0xd2, 0x79, 0x4d, 0x09, 0x4f });
static ge_p3 G_p3;
static ge_p3 H_p3;
static ge_p3 X_p3;
Expand Down Expand Up @@ -167,9 +167,9 @@ static public_key reproduce_generator_X()
//-------------------------------------------------------------------------------------------------------------------
static public_key reproduce_generator_U()
{
// U = H_p(keccak("seraphis_U"))
// U = H_p(keccak("Monero Generator T"))
const std::string U_salt{config::HASH_KEY_SERAPHIS_U};
hash U_temp_hash{cn_fast_hash(U_salt.data(), U_salt.size())};
const hash U_temp_hash{cn_fast_hash(U_salt.data(), U_salt.size())};
public_key reproduced_U;
hash_to_point(U_temp_hash, reproduced_U);

Expand All @@ -187,7 +187,7 @@ static void init_gens()
static_assert(static_cast<unsigned char>(G.data[0]) == 0x58, "compile-time constant sanity check");
static_assert(static_cast<unsigned char>(H.data[0]) == 0x8b, "compile-time constant sanity check");
static_assert(static_cast<unsigned char>(X.data[0]) == 0xa4, "compile-time constant sanity check");
static_assert(static_cast<unsigned char>(U.data[0]) == 0x10, "compile-time constant sanity check");
static_assert(static_cast<unsigned char>(U.data[0]) == 0x96, "compile-time constant sanity check");

// build ge_p3 representations of generators
const int G_deserialize = ge_frombytes_vartime(&G_p3, to_bytes(G));
Expand Down
4 changes: 4 additions & 0 deletions src/crypto/x25519.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ void x25519_invmul_key(std::vector<x25519_secret_key> privkeys_to_invert,

} //namespace crypto

inline const unsigned char* to_bytes(const crypto::x25519_pubkey &point) { return &reinterpret_cast<const unsigned char&>(point); }
inline const unsigned char* to_bytes(const crypto::x25519_scalar &scalar) { return &reinterpret_cast<const unsigned char&>(scalar); }
inline const unsigned char* to_bytes(const crypto::x25519_secret_key &skey) { return &reinterpret_cast<const unsigned char&>(skey); }

/// upgrade x25519 keys
CRYPTO_MAKE_HASHABLE(x25519_pubkey)
CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(x25519_scalar)
Expand Down
1 change: 1 addition & 0 deletions src/cryptonote_basic/cryptonote_format_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ namespace cryptonote
if (!pick<tx_extra_merge_mining_tag>(nar, tx_extra_fields, TX_EXTRA_MERGE_MINING_TAG)) return false;
if (!pick<tx_extra_mysterious_minergate>(nar, tx_extra_fields, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG)) return false;
if (!pick<tx_extra_padding>(nar, tx_extra_fields, TX_EXTRA_TAG_PADDING)) return false;
if (!pick<tx_extra_jamtis_v1>(nar, tx_extra_fields, TX_EXTRA_TAG_JAMTIS_V1)) return false;

// if not empty, someone added a new type and did not add a case above
if (!tx_extra_fields.empty())
Expand Down
34 changes: 33 additions & 1 deletion src/cryptonote_basic/tx_extra.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#define TX_EXTRA_NONCE 0x02
#define TX_EXTRA_MERGE_MINING_TAG 0x03
#define TX_EXTRA_TAG_ADDITIONAL_PUBKEYS 0x04
#define TX_EXTRA_TAG_JAMTIS_V1 0x05
#define TX_EXTRA_MYSTERIOUS_MINERGATE_TAG 0xDE

#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
Expand Down Expand Up @@ -165,6 +166,29 @@ namespace cryptonote
END_SERIALIZE()
};

struct tx_extra_jamtis_v1
{
struct enote_entry_t
{
unsigned char addr_tag_enc[16];
unsigned char view_tag[3]; // other 1 byte of view tag stored in tx_out
// encrypted amount stored in ecdhInfo
};
static_assert(sizeof(enote_entry_t) == 19, "enote_entry wrong size");
static_assert(std::is_standard_layout_v<enote_entry_t>, "enote_entry_t does not have standard layout");

std::vector<enote_entry_t> output_info;
std::vector<crypto::x25519_pubkey> enote_ephemeral_pubkeys;
std::uint8_t num_primary_view_tag_bits;
// encrypted payment ID can be added with tx_extra_nonce

BEGIN_SERIALIZE_OBJECT()
FIELD(output_info)
FIELD(enote_ephemeral_pubkeys)
FIELD(num_primary_view_tag_bits)
END_SERIALIZE()
};

struct tx_extra_mysterious_minergate
{
std::string data;
Expand All @@ -178,12 +202,20 @@ namespace cryptonote
// varint tag;
// varint size;
// varint data[];
typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag, tx_extra_additional_pub_keys, tx_extra_mysterious_minergate> tx_extra_field;
typedef boost::variant<tx_extra_padding,
tx_extra_pub_key,
tx_extra_nonce,
tx_extra_merge_mining_tag,
tx_extra_additional_pub_keys,
tx_extra_jamtis_v1,
tx_extra_mysterious_minergate> tx_extra_field;
}

BLOB_SERIALIZER(cryptonote::tx_extra_jamtis_v1::enote_entry_t);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_pub_key, TX_EXTRA_TAG_PUBKEY);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_merge_mining_tag, TX_EXTRA_MERGE_MINING_TAG);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_additional_pub_keys, TX_EXTRA_TAG_ADDITIONAL_PUBKEYS);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_jamtis_v1, TX_EXTRA_TAG_JAMTIS_V1);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_mysterious_minergate, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG);
29 changes: 16 additions & 13 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ namespace config
const constexpr char HASH_KEY_TXHASH_AND_MIXRING[] = "txhash_and_mixring";
const constexpr char HASH_KEY_MULTISIG_BINONCE_MERGE_FACTOR[] = "multisig_binonce_merge_factor";
const constexpr char HASH_KEY_SERAPHIS_X[] = "seraphis_X";
const constexpr char HASH_KEY_SERAPHIS_U[] = "seraphis_U";
const constexpr char HASH_KEY_SERAPHIS_U[] = "Monero Generator T"; // to match https://github.com/kayabaNerve/fcmp-plus-plus/blob/00242acf9a1402d6361f057e51deecebf73e17b4/coins/monero/generators/src/lib.rs#L39-L44

const constexpr char TRANSCRIPT_PREFIX[] = "monero";

Expand Down Expand Up @@ -307,33 +307,36 @@ namespace config
const constexpr char HASH_KEY_BINNED_REF_SET_GENERATOR_SEED[] = "binned_refset_generator_seed";
const constexpr char HASH_KEY_BINNED_REF_SET_MEMBER[] = "binned_refset_member";

const constexpr char HASH_KEY_JAMTIS_VIEWBALANCE_KEY[] = "jamtis_view_balance_key";
const constexpr char HASH_KEY_JAMTIS_UNLOCKAMOUNTS_KEY[] = "jamtis_unlock_amounts_key";
const constexpr char HASH_KEY_JAMTIS_PROVESPEND_KEY[] = "jamtis_prove_spend_key";
const constexpr char HASH_KEY_JAMTIS_VIEWBALANCE_SECRET[] = "jamtis_view_balance_secret";
const constexpr char HASH_KEY_JAMTIS_GENERATEIMAGE_KEY[] = "jamtis_generate_image_key";
const constexpr char HASH_KEY_JAMTIS_UNLOCKRECEIVED_KEY[] = "jamtis_unlock_received_key";
const constexpr char HASH_KEY_JAMTIS_IDENTIFYRECEIVED_KEY[] = "jamtis_identify_received_key";
const constexpr char HASH_KEY_JAMTIS_FILTERASSIST_KEY[] = "jamtis_filter_assist_key";
const constexpr char HASH_KEY_JAMTIS_GENERATEADDRESS_SECRET[] = "jamtis_generate_address_secret";
const constexpr char HASH_KEY_JAMTIS_CIPHERTAG_SECRET[] = "jamtis_cipher_tag_secret";
const constexpr char HASH_KEY_JAMTIS_FINDRECEIVED_KEY[] = "jamtis_find_received_key";
const constexpr char HASH_KEY_JAMTIS_INDEX_EXTENSION_GENERATOR[] = "jamtis_index_extension_generator";
const constexpr char HASH_KEY_JAMTIS_ADDRESS_PRIVKEY[] = "jamtis_address_privkey";
const constexpr char HASH_KEY_JAMTIS_SPENDKEY_EXTENSION_G[] = "jamtis_spendkey_extension_g";
const constexpr char HASH_KEY_JAMTIS_SPENDKEY_EXTENSION_X[] = "jamtis_spendkey_extension_x";
const constexpr char HASH_KEY_JAMTIS_SPENDKEY_EXTENSION_U[] = "jamtis_spendkey_extension_u";
const constexpr char HASH_KEY_JAMTIS_ADDRESS_TAG_HINT[] = "jamtis_address_tag_hint";
const constexpr char HASH_KEY_JAMTIS_ENCRYPTED_ADDRESS_TAG[] = "jamtis_encrypted_address_tag";
const constexpr char HASH_KEY_JAMTIS_VIEW_TAG[] = "jamtis_view_tag";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_PLAIN[] = "jamtis_sr_secret_plain";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_DUMMY[] = "jamtis_selfsend_dummy";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_CHANGE[] = "jamtis_selfsend_change";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET_SELFSEND_SELF_SPEND[] = "jamtis_selfsend_self_spend";
const constexpr char HASH_KEY_JAMTIS_ENCRYPTED_AMOUNT_MASK[] = "jamtis_encrypted_amount_mask";
const constexpr char HASH_KEY_JAMTIS_ENCRYPTED_PAYMENT_ID_MASK[] = "jamtis_encrypted_payment_id_mask";
const constexpr char HASH_KEY_JAMTIS_VIEW_TAG_PRIMARY[] = "jamtis_view_tag_primary";
const constexpr char HASH_KEY_JAMTIS_VIEW_TAG_SECONDARY[] = "jamtis_view_tag_secondary";
const constexpr char HASH_KEY_JAMTIS_SENDER_RECEIVER_SECRET[] = "jamtis_sr_secret";
const constexpr char HASH_KEY_JAMTIS_SENDER_ONETIME_ADDRESS_EXTENSION_G[] = "jamtis_sender_extension_g";
const constexpr char HASH_KEY_JAMTIS_SENDER_ONETIME_ADDRESS_EXTENSION_X[] = "jamtis_sender_extension_x";
const constexpr char HASH_KEY_JAMTIS_SENDER_ONETIME_ADDRESS_EXTENSION_U[] = "jamtis_sender_extension_u";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_PLAIN[] = "jamtis_amount_baked_key_plain";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BAKED_KEY_SELFSEND[] = "jamtis_amount_baked_key_selfsend";
const constexpr char HASH_KEY_JAMTIS_AMOUNT_BLINDING_FACTOR[] = "jamtis_amount_commitment_blinding_factor";
const constexpr char HASH_KEY_JAMTIS_ENCODED_AMOUNT_MASK[] = "jamtis_encoded_amount_mask";
const constexpr char HASH_KEY_JAMTIS_INPUT_CONTEXT_COINBASE[] = "jamtis_input_context_coinbase";
const constexpr char HASH_KEY_JAMTIS_INPUT_CONTEXT_STANDARD[] = "jamtis_input_context_standard";

const constexpr char HASH_KEY_CARROT_CHANGE_SPEND_EXTENSION_G[] = "carrot_change_spend_extension_g";
const constexpr char HASH_KEY_CARROT_CHANGE_SPEND_EXTENSION_U[] = "carrot_change_spend_extension_u";
const constexpr char HASH_KEY_CARROT_ENOTE_EPHEMERAL_PRIVKEY[] = "carrot_enote_ephemeral_privkey";

// Multisig
const uint32_t MULTISIG_MAX_SIGNERS{16};

Expand Down
3 changes: 2 additions & 1 deletion src/seraphis_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@
set(seraphis_core_sources
binned_reference_set.cpp
binned_reference_set_utils.cpp
carrot_payment_proposal.cpp
discretized_fee.cpp
jamtis_account_secrets.cpp
jamtis_address_tag_utils.cpp
jamtis_address_utils.cpp
jamtis_core_utils.cpp
jamtis_destination.cpp
jamtis_enote_utils.cpp
jamtis_payment_proposal.cpp
Expand Down
Loading

0 comments on commit afe5119

Please sign in to comment.