diff --git a/contrib/monero-core-custom b/contrib/monero-core-custom index 4f29efe..7cc72f5 160000 --- a/contrib/monero-core-custom +++ b/contrib/monero-core-custom @@ -1 +1 @@ -Subproject commit 4f29efe73f06af98037a65d2eb1332267555cd97 +Subproject commit 7cc72f59cc8765970c6bdf31a56aa0d691cba15e diff --git a/src/monero_transfer_utils.cpp b/src/monero_transfer_utils.cpp index 4d11a06..bd03534 100644 --- a/src/monero_transfer_utils.cpp +++ b/src/monero_transfer_utils.cpp @@ -93,6 +93,7 @@ bool monero_transfer_utils::is_tx_spendtime_unlocked( return false; } // +namespace { CreateTransactionErrorCode _add_pid_to_tx_extra( const optional& payment_id_string, vector &extra @@ -149,24 +150,40 @@ bool _rct_hex_to_decrypted_mask( if (rct_string.empty()) { return false; } - // rct_string is a string with length 64+64+64 ( + + ) + // rct_string is a magic value if output is RCT and coinbase + if (rct_string == "coinbase") { + decrypted_mask = rct::identity(); + return true; + } + auto make_key_derivation = [&]() { + crypto::key_derivation derivation; + bool r = generate_key_derivation(tx_pub_key, view_secret_key, derivation); + THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); + crypto::secret_key scalar; + crypto::derivation_to_scalar(derivation, internal_output_index, scalar); + return rct::sk2rct(scalar); + }; rct::key encrypted_mask; + // rct_string is a string with length 64+16 ( + ) if RCT version 2 + if (rct_string.size() < 64 * 2) { + decrypted_mask = rct::genCommitmentMask(make_key_derivation()); + return true; + } + // rct_string is a string with length 64+64+64 ( + + ) std::string encrypted_mask_str = rct_string.substr(64,64); THROW_WALLET_EXCEPTION_IF(!string_tools::validate_hex(64, encrypted_mask_str), error::wallet_internal_error, "Invalid rct mask: " + encrypted_mask_str); string_tools::hex_to_pod(encrypted_mask_str, encrypted_mask); // - if (encrypted_mask == rct::identity()) { // NOTE: ringct coinbase txs have the identity mask manually provided unencrypted in the rct field by the hosted lightwallet backend + if (encrypted_mask == rct::identity()) { + // backward compatibility; should no longer be needed after v11 mainnet fork decrypted_mask = encrypted_mask; return true; } // // Decrypt the mask - crypto::key_derivation derivation; - bool r = generate_key_derivation(tx_pub_key, view_secret_key, derivation); - THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); - crypto::secret_key scalar; - crypto::derivation_to_scalar(derivation, internal_output_index, scalar); - sc_sub(decrypted_mask.bytes, encrypted_mask.bytes, rct::hash_to_scalar(rct::sk2rct(scalar)).bytes); + sc_sub(decrypted_mask.bytes, + encrypted_mask.bytes, + rct::hash_to_scalar(make_key_derivation()).bytes); return true; } @@ -176,6 +193,7 @@ bool _verify_sec_key(const crypto::secret_key &secret_key, const crypto::public_ bool r = crypto::secret_key_to_public_key(secret_key, calculated_pub); return r && public_key == calculated_pub; } +} // unnamed namespace // namespace { @@ -557,7 +575,9 @@ void monero_transfer_utils::create_transaction( } real_oe.second.dest = rct::pk2rct(public_key); // - if (outputs[out_index].rct != none && (*(outputs[out_index].rct)).empty() == false) { + if (outputs[out_index].rct != none + && outputs[out_index].rct->empty() == false + && *outputs[out_index].rct != "coinbase") { rct::key commit; _rct_hex_to_rct_commit(*(outputs[out_index].rct), commit); real_oe.second.mask = commit; //add commitment for real input @@ -612,9 +632,7 @@ void monero_transfer_utils::create_transaction( // return; // } } else { - rct::key I; - rct::identity(I); - src.mask = I; // in the original cn_utils impl this was left as null for generate_key_image_helper_rct to fill in with identity I + rct::identity(src.mask); // in the original cn_utils impl this was left as null for generate_key_image_helper_rct to fill in with identity I } // not doing multisig here yet src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()});