diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 0c67d9d33..739943242 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -67,6 +67,8 @@ namespace cryptonote struct txout_to_carrot_v1 { crypto::public_key key; // K_o + std::string asset_type; + uint64_t unlock_time; carrot::view_tag_t view_tag; // vt carrot::encrypted_janus_anchor_t encrypted_janus_anchor; // anchor_enc @@ -75,11 +77,24 @@ namespace cryptonote BEGIN_SERIALIZE_OBJECT() FIELD(key) + FIELD(asset_type) + VARINT_FIELD(unlock_time) FIELD(view_tag) FIELD(encrypted_janus_anchor) END_SERIALIZE() }; + struct txout_to_script + { + std::vector keys; + std::vector script; + + BEGIN_SERIALIZE_OBJECT() + FIELD(keys) + FIELD(script) + END_SERIALIZE() + }; + struct txout_to_scripthash { crypto::hash hash; @@ -168,7 +183,7 @@ namespace cryptonote typedef boost::variant txin_v; - typedef boost::variant txout_target_v; + typedef boost::variant txout_target_v; //typedef std::pair out_t; struct tx_out @@ -734,10 +749,11 @@ VARIANT_TAG(binary_archive, cryptonote::txin_gen, 0xff); VARIANT_TAG(binary_archive, cryptonote::txin_to_script, 0x0); VARIANT_TAG(binary_archive, cryptonote::txin_to_scripthash, 0x1); VARIANT_TAG(binary_archive, cryptonote::txin_to_key, 0x2); -VARIANT_TAG(binary_archive, cryptonote::txout_to_carrot_v1, 0x0); +VARIANT_TAG(binary_archive, cryptonote::txout_to_script, 0x0); VARIANT_TAG(binary_archive, cryptonote::txout_to_scripthash, 0x1); VARIANT_TAG(binary_archive, cryptonote::txout_to_key, 0x2); VARIANT_TAG(binary_archive, cryptonote::txout_to_tagged_key, 0x3); +VARIANT_TAG(binary_archive, cryptonote::txout_to_carrot_v1, 0x4); VARIANT_TAG(binary_archive, cryptonote::transaction, 0xcc); VARIANT_TAG(binary_archive, cryptonote::block, 0xbb); @@ -745,10 +761,11 @@ VARIANT_TAG(json_archive, cryptonote::txin_gen, "gen"); VARIANT_TAG(json_archive, cryptonote::txin_to_script, "script"); VARIANT_TAG(json_archive, cryptonote::txin_to_scripthash, "scripthash"); VARIANT_TAG(json_archive, cryptonote::txin_to_key, "key"); -VARIANT_TAG(json_archive, cryptonote::txout_to_carrot_v1, "carrot_v1"); +VARIANT_TAG(json_archive, cryptonote::txout_to_script, "script"); VARIANT_TAG(json_archive, cryptonote::txout_to_scripthash, "scripthash"); VARIANT_TAG(json_archive, cryptonote::txout_to_key, "key"); VARIANT_TAG(json_archive, cryptonote::txout_to_tagged_key, "tagged_key"); +VARIANT_TAG(json_archive, cryptonote::txout_to_carrot_v1, "carrot_v1"); VARIANT_TAG(json_archive, cryptonote::transaction, "tx"); VARIANT_TAG(json_archive, cryptonote::block, "block"); @@ -756,9 +773,10 @@ VARIANT_TAG(debug_archive, cryptonote::txin_gen, "gen"); VARIANT_TAG(debug_archive, cryptonote::txin_to_script, "script"); VARIANT_TAG(debug_archive, cryptonote::txin_to_scripthash, "scripthash"); VARIANT_TAG(debug_archive, cryptonote::txin_to_key, "key"); -VARIANT_TAG(debug_archive, cryptonote::txout_to_carrot_v1, "carrot_v1"); +VARIANT_TAG(debug_archive, cryptonote::txout_to_script, "script"); VARIANT_TAG(debug_archive, cryptonote::txout_to_scripthash, "scripthash"); VARIANT_TAG(debug_archive, cryptonote::txout_to_key, "key"); VARIANT_TAG(debug_archive, cryptonote::txout_to_tagged_key, "tagged_key"); +VARIANT_TAG(debug_archive, cryptonote::txout_to_carrot_v1, "carrot_v1"); VARIANT_TAG(debug_archive, cryptonote::transaction, "tx"); VARIANT_TAG(debug_archive, cryptonote::block, "block"); diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 53d05a0d8..17d9e814d 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -94,14 +94,12 @@ namespace boost } template - inline void serialize(Archive &a, cryptonote::txout_to_carrot_v1 &x, const boost::serialization::version_type ver) + inline void serialize(Archive &a, cryptonote::txout_to_script &x, const boost::serialization::version_type ver) { - a & x.key; - a & x.view_tag; - a & x.encrypted_janus_anchor; + a & x.keys; + a & x.script; } - template inline void serialize(Archive &a, cryptonote::txout_to_key &x, const boost::serialization::version_type ver) { @@ -110,6 +108,16 @@ namespace boost a & x.unlock_time; } + template + inline void serialize(Archive &a, cryptonote::txout_to_carrot_v1 &x, const boost::serialization::version_type ver) + { + a & x.key; + a & x.asset_type; + a & x.unlock_time; + a & x.view_tag; + a & x.encrypted_janus_anchor; + } + template inline void serialize(Archive &a, cryptonote::txout_to_tagged_key &x, const boost::serialization::version_type ver) { diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index e80130913..3a5ff091b 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -290,6 +290,182 @@ namespace cryptonote return is_v1_tx(blobdata_ref{tx_blob.data(), tx_blob.size()}); } //--------------------------------------------------------------- + bool generate_key_image_helper(const account_keys& ack, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const bool use_origin_data, const origin_data& od, rct::salvium_input_data_t& sid) + { + crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation); + bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation); + if (!r) + { + MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", )"); + memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation)); + } + + std::vector additional_recv_derivations; + for (size_t i = 0; i < additional_tx_public_keys.size(); ++i) + { + crypto::key_derivation additional_recv_derivation = AUTO_VAL_INIT(additional_recv_derivation); + r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation); + if (!r) + { + MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", )"); + } + else + { + additional_recv_derivations.push_back(additional_recv_derivation); + } + } + + boost::optional subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index,hwdev); + CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address"); + + sid.aR = subaddr_recv_info->derivation; + sid.i = real_output_index; + return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, subaddr_recv_info->index, in_ephemeral, ki, hwdev, use_origin_data, od, sid); + } + //--------------------------------------------------------------- + bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const bool use_origin_data, const origin_data& od, rct::salvium_input_data_t& sid) + { + if (hwdev.compute_key_image(ack, out_key, recv_derivation, real_output_index, received_index, in_ephemeral, ki)) + { + return true; + } + + if (ack.m_spend_secret_key == crypto::null_skey) + { + // for watch-only wallet, simply copy the known output pubkey + in_ephemeral.pub = out_key; + in_ephemeral.sec = crypto::null_skey; + } + else + { + // derive secret key with subaddress - step 1: original CN derivation + crypto::secret_key scalar_step1; + crypto::secret_key spend_skey = crypto::null_skey; + + if (ack.m_multisig_keys.empty()) + { + // if not multisig, use normal spend skey + spend_skey = ack.m_spend_secret_key; + } + else + { + // if multisig, use sum of multisig privkeys (local account's share of aggregate spend key) + for (const auto &multisig_key : ack.m_multisig_keys) + { + sc_add((unsigned char*)spend_skey.data, + (const unsigned char*)multisig_key.data, + (const unsigned char*)spend_skey.data); + } + } + + // computes Hs(a*R || idx) + b + hwdev.derive_secret_key(recv_derivation, real_output_index, spend_skey, scalar_step1); + + // step 2: add Hs(a || index_major || index_minor) + crypto::secret_key subaddr_sk; + crypto::secret_key scalar_step2; + if (received_index.is_zero()) + { + scalar_step2 = scalar_step1; // treat index=(0,0) as a special case representing the main address + } + else + { + subaddr_sk = hwdev.get_subaddress_secret_key(ack.m_view_secret_key, received_index); + hwdev.sc_secret_add(scalar_step2, scalar_step1,subaddr_sk); + } + + in_ephemeral.sec = scalar_step2; + + if (ack.m_multisig_keys.empty()) + { + // when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase + CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key"); + } + else + { + // when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation + CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key"); + // and don't forget to add the contribution from the subaddress part + if (!received_index.is_zero()) + { + crypto::public_key subaddr_pk; + CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key"); + add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk); + } + } + + if (in_ephemeral.pub != out_key) { + if (use_origin_data) { + + // 1. Obtain P_change from the output (it is the subaddress public key) + crypto::public_key P_change = crypto::null_pkey; + // SRCG: This is a confusing one - for some reason I was using the line below, and it _seemed_ to work... + // ... but I think it was luck! the "od.output_index" would only work for the TD_ORIGIN data, of course... + //hwdev.derive_subaddress_public_key(out_key, recv_derivation, od.output_index, P_change); + if (od.tx_type == cryptonote::transaction_type::CONVERT || od.tx_type == cryptonote::transaction_type::STAKE || od.tx_type == cryptonote::transaction_type::AUDIT) { + hwdev.derive_subaddress_public_key(out_key, recv_derivation, 0, P_change); + } else { + hwdev.derive_subaddress_public_key(out_key, recv_derivation, real_output_index, P_change); + } + + // 2. Obtain a separate key_derivation for the _original_ P_change output + // (using the TX public key from the CONVERT TX and the sender's private view key) + crypto::key_derivation derivation_P_change_tx = AUTO_VAL_INIT(derivation_P_change_tx); + CHECK_AND_ASSERT_MES(hwdev.generate_key_derivation(od.tx_pub_key, ack.m_view_secret_key, derivation_P_change_tx), false, "Failed to generate key_derivation for P_change"); + + // 3. Calculate the secret spend key "x_change" for the change output of the CONVERT TX + crypto::secret_key sk_spend = crypto::null_skey; + CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(derivation_P_change_tx, od.output_index, spend_skey, sk_spend), false, "Failed to derive secret key for P_change"); + + // 3.5 Handle subaddresses + if (!received_index.is_zero()) { + crypto::secret_key scalar_step3; + hwdev.sc_secret_add(scalar_step3, sk_spend, subaddr_sk); + sk_spend = scalar_step3; + } + + // 4. Derive the public key from the secret key for verification purposes + crypto::public_key change_pk; + CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(sk_spend, change_pk), false, "Failed to derive public key for P_change"); + CHECK_AND_ASSERT_MES(P_change == change_pk, false, "derived P_change public key does not match P_change"); + + // 5. Calculate the secret spend key "x_return" + if (od.tx_type == cryptonote::transaction_type::CONVERT || od.tx_type == cryptonote::transaction_type::STAKE || od.tx_type == cryptonote::transaction_type::AUDIT) { + CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, 0, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'"); + } else { + CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, real_output_index, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'"); + } + in_ephemeral.sec = scalar_step1; + CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive one-time output public key 'P_return'"); + CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, + false, "key image helper precomp: given output pubkey doesn't match the derived one"); + + // 6. Create the key_image needed to be able to spend the output + hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); + + // Update the SID to have the correct derivation for P_change as well + sid.aR_stake = derivation_P_change_tx; + sid.i_stake = od.output_index; + + return true; + + } else { + + // Not really anything to do here except throw an exception + CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, + false, "key image helper precomp: given output pubkey doesn't match the derived one"); + } + } + + CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, + false, "key image helper precomp: given output pubkey doesn't match the derived one"); + } + + hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); + return true; + } + /* + //--------------------------------------------------------------- bool generate_key_image_helper(const account_keys& ack, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev) { crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation); @@ -399,6 +575,7 @@ namespace cryptonote hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); return true; } + */ //--------------------------------------------------------------- uint64_t power_integral(uint64_t a, uint64_t b) { diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index ccf4104b7..c7a83ea8d 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -107,8 +107,8 @@ namespace cryptonote bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered); bool get_tx_fee(const transaction& tx, uint64_t & fee); uint64_t get_tx_fee(const transaction& tx); - bool generate_key_image_helper(const account_keys& ack, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); - bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); + bool generate_key_image_helper(const account_keys& ack, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const bool use_origin_data, const origin_data& od, rct::salvium_input_data_t& sid); + bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const bool use_origin_data, const origin_data& od, rct::salvium_input_data_t& sid); void get_blob_hash(const blobdata& blob, crypto::hash& res); void get_blob_hash(const blobdata_ref& blob, crypto::hash& res); crypto::hash get_blob_hash(const blobdata& blob); diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 4f5e69e4f..07af623fd 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #define CRYPTONOTE_DNS_TIMEOUT_MS 20000 diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 1e6d52114..5eb9c9a4c 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -811,7 +811,7 @@ namespace cryptonote const auto& out_key = reinterpret_cast(src_entr.outputs[src_entr.real_output].second.dest); bool use_origin_data = (src_entr.origin_tx_data.tx_type != cryptonote::transaction_type::UNSET); sid.origin_tx_type = src_entr.origin_tx_data.tx_type; - if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral,img, hwdev)) + if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral,img, hwdev, use_origin_data, src_entr.origin_tx_data, sid)) { LOG_ERROR("Key image generation failed!"); return false; diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp index ecf91f49b..70f734b35 100644 --- a/src/multisig/multisig.cpp +++ b/src/multisig/multisig.cpp @@ -101,7 +101,7 @@ namespace multisig // - later, we add in the components held by other participants cryptonote::keypair in_ephemeral; - if (!cryptonote::generate_key_image_helper(keys, subaddresses, out_key, tx_public_key, additional_tx_public_keys, real_output_index, in_ephemeral, ki, keys.get_device())) + if (!cryptonote::generate_key_image_helper(keys, subaddresses, out_key, tx_public_key, additional_tx_public_keys, real_output_index, in_ephemeral, ki, keys.get_device(), use_origin_data, origin_tx_data, sid)) return false; std::unordered_set used; diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index 4a211a8b8..f9a510a69 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -186,7 +186,10 @@ static bool compute_keys_for_sources( src.real_output_in_tx_index, tmp_keys, tmp_key_image, - hwdev + hwdev, + use_origin_data, + src.origin_tx_data, + sid )) { return false; } diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index a9e9ea8d4..8a87e4e49 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -530,27 +530,25 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_key& txin) } -void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_carrot_v1& txout) +void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_script& txout) { dest.StartObject(); - INSERT_INTO_JSON_OBJECT(dest, key, txout.key); - INSERT_INTO_JSON_OBJECT(dest, view_tag, txout.view_tag); - INSERT_INTO_JSON_OBJECT(dest, encrypted_janus_anchor, txout.encrypted_janus_anchor); + INSERT_INTO_JSON_OBJECT(dest, keys, txout.keys); + INSERT_INTO_JSON_OBJECT(dest, script, txout.script); dest.EndObject(); } -void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_carrot_v1& txout) +void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_script& txout) { if (!val.IsObject()) { throw WRONG_TYPE("json object"); } - GET_FROM_JSON_OBJECT(val, txout.key, key); - GET_FROM_JSON_OBJECT(val, txout.view_tag, view_tag); - GET_FROM_JSON_OBJECT(val, txout.encrypted_janus_anchor, encrypted_janus_anchor); + GET_FROM_JSON_OBJECT(val, txout.keys, keys); + GET_FROM_JSON_OBJECT(val, txout.script, script); } @@ -622,6 +620,34 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_tagged_key& GET_FROM_JSON_OBJECT(val, txout.view_tag, view_tag); } +void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_carrot_v1& txout) +{ + dest.StartObject(); + + INSERT_INTO_JSON_OBJECT(dest, key, txout.key); + INSERT_INTO_JSON_OBJECT(dest, asset_type, txout.asset_type); + INSERT_INTO_JSON_OBJECT(dest, unlock_time, txout.unlock_time); + INSERT_INTO_JSON_OBJECT(dest, view_tag, txout.view_tag); + INSERT_INTO_JSON_OBJECT(dest, encrypted_janus_anchor, txout.encrypted_janus_anchor); + + dest.EndObject(); +} + +void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_carrot_v1& txout) +{ + if (!val.IsObject()) + { + throw WRONG_TYPE("json object"); + } + + GET_FROM_JSON_OBJECT(val, txout.key, key); + GET_FROM_JSON_OBJECT(val, txout.asset_type, asset_type); + GET_FROM_JSON_OBJECT(val, txout.unlock_time, unlock_time); + GET_FROM_JSON_OBJECT(val, txout.view_tag, view_tag); + GET_FROM_JSON_OBJECT(val, txout.encrypted_janus_anchor, encrypted_janus_anchor); +} + + void toJsonValue(rapidjson::Writer& dest, const cryptonote::tx_out& txout) { dest.StartObject(); @@ -645,6 +671,10 @@ void toJsonValue(rapidjson::Writer& dest, const cryptonote::t { INSERT_INTO_JSON_OBJECT(dest, to_carrot_v1, output); } + void operator()(cryptonote::txout_to_script const& output) const + { + INSERT_INTO_JSON_OBJECT(dest, to_script, output); + } void operator()(cryptonote::txout_to_scripthash const& output) const { INSERT_INTO_JSON_OBJECT(dest, to_scripthash, output); @@ -691,6 +721,12 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout) fromJsonValue(elem.value, tmpVal); txout.target = std::move(tmpVal); } + else if (elem.name == "to_script") + { + cryptonote::txout_to_script tmpVal; + fromJsonValue(elem.value, tmpVal); + txout.target = std::move(tmpVal); + } else if (elem.name == "to_scripthash") { cryptonote::txout_to_scripthash tmpVal; diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h index 998caea32..73d46b4ea 100644 --- a/src/serialization/json_object.h +++ b/src/serialization/json_object.h @@ -221,8 +221,8 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txin_to_key& txin); void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_target_v& txout); void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_target_v& txout); -void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_carrot_v1& txout); -void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_carrot_v1& txout); +void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_script& txout); +void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_script& txout); void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_scripthash& txout); void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_scripthash& txout); @@ -233,6 +233,9 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_key& txout) void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_tagged_key& txout); void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_tagged_key& txout); +void toJsonValue(rapidjson::Writer& dest, const cryptonote::txout_to_carrot_v1& txout); +void fromJsonValue(const rapidjson::Value& val, cryptonote::txout_to_carrot_v1& txout); + void toJsonValue(rapidjson::Writer& dest, const cryptonote::tx_out& txout); void fromJsonValue(const rapidjson::Value& val, cryptonote::tx_out& txout); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 40865a3ec..3f6ec43c6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7866,7 +7866,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector in_additionakl_tx_pub_keys = get_additional_tx_pub_keys_from_extra(in_td.m_tx); keypair in_ephemeral; crypto::key_image in_img; - THROW_WALLET_EXCEPTION_IF(!generate_key_image_helper(m_account.get_keys(), m_subaddresses, in_tx_out_pkey, in_tx_pub_key, in_additionakl_tx_pub_keys, in_td.m_internal_output_index, in_ephemeral, in_img, m_account.get_device()), + THROW_WALLET_EXCEPTION_IF(!generate_key_image_helper(m_account.get_keys(), m_subaddresses, in_tx_out_pkey, in_tx_pub_key, in_additionakl_tx_pub_keys, in_td.m_internal_output_index, in_ephemeral, in_img, m_account.get_device(), false, origin_tx_data, sid), error::wallet_internal_error, "failed to generate key image"); THROW_WALLET_EXCEPTION_IF(in_key->k_image != in_img, error::wallet_internal_error, "key image mismatch"); @@ -12995,7 +12995,7 @@ std::string wallet2::get_reserve_proof(const boost::optional> // generate ephemeral secret key crypto::key_image ki; cryptonote::keypair in_ephemeral; - bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, pkey, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, ki, m_account.get_device()); + bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, pkey, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, ki, m_account.get_device(), false, od, sid); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image"); THROW_WALLET_EXCEPTION_IF(td.m_key_image_known && !td.m_key_image_partial && ki != td.m_key_image, @@ -14585,7 +14585,7 @@ process: crypto::public_key out_key = td.get_public_key(); if (should_expand(td.m_subaddr_index)) create_one_off_subaddress(td.m_subaddr_index); - bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device()); + bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device(), false, od, sid); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image"); if (should_expand(td.m_subaddr_index)) expand_subaddresses(td.m_subaddr_index); @@ -14694,7 +14694,7 @@ size_t wallet2::import_outputs(const std::tuple(src_entr.outputs[src_entr.real_output].second.dest); rct::salvium_input_data_t sid; const cryptonote::origin_data od{3, crypto::null_pkey, src_entr.real_output}; - generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral, img, hw::get_device(("default"))); + generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral, img, hw::get_device(("default")), false, od, sid); // put key image into tx input txin_to_key input_to_key; diff --git a/tests/performance_tests/generate_key_image_helper.h b/tests/performance_tests/generate_key_image_helper.h index 3ee536b58..2308bb84a 100644 --- a/tests/performance_tests/generate_key_image_helper.h +++ b/tests/performance_tests/generate_key_image_helper.h @@ -51,6 +51,6 @@ public: crypto::public_key out_key = boost::get(m_tx.vout[0].target).key; cryptonote::origin_data od{3,crypto::null_pkey,0}; rct::salvium_input_data_t sid; - return cryptonote::generate_key_image_helper(m_bob.get_keys(), subaddresses, out_key, m_tx_pub_key, m_additional_tx_pub_keys, 0, in_ephemeral, ki, hw::get_device("default")); + return cryptonote::generate_key_image_helper(m_bob.get_keys(), subaddresses, out_key, m_tx_pub_key, m_additional_tx_pub_keys, 0, in_ephemeral, ki, hw::get_device("default"), false, od, sid); } };