diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 759e51290..e77b0146f 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -170,13 +170,15 @@ namespace boost a & x.vout; a & x.extra; a & x.type; - if (x.type != cryptonote::transaction_type::MINER && x.type != cryptonote::transaction_type::PROTOCOL) { - a & x.return_address; - a & x.return_pubkey; - a & x.source_asset_type; - a & x.destination_asset_type; + if (x.type != cryptonote::transaction_type::PROTOCOL) { a & x.amount_burnt; - a & x.amount_slippage_limit; + if (x.type != cryptonote::transaction_type::MINER) { + a & x.return_address; + a & x.return_pubkey; + a & x.source_asset_type; + a & x.destination_asset_type; + a & x.amount_slippage_limit; + } } } diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp index 6c3d265ad..78622b11f 100644 --- a/src/multisig/multisig.cpp +++ b/src/multisig/multisig.cpp @@ -84,13 +84,15 @@ namespace multisig } //---------------------------------------------------------------------------------------------------------------------- bool generate_multisig_composite_key_image(const cryptonote::account_keys &keys, - 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, - std::size_t real_output_index, - const std::vector &pkis, - crypto::key_image &ki) + 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, + std::size_t real_output_index, + const std::vector &pkis, + crypto::key_image &ki, + const bool use_origin_data, + const cryptonote::origin_data& origin_tx_data) { // create a multisig partial key image // KI_partial = ([view key component] + [subaddress component] + [multisig privkeys]) * Hp(output one-time address) @@ -98,11 +100,7 @@ namespace multisig // - later, we add in the components held by other participants cryptonote::keypair in_ephemeral; - // Populate this struct if you want to make use of multisig for Salvium!!! - assert(false); - cryptonote::origin_data origin_tx_data; - - 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(), true, origin_tx_data)) + 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)) return false; std::unordered_set used; diff --git a/src/multisig/multisig.h b/src/multisig/multisig.h index 16dbbc544..849e59eca 100644 --- a/src/multisig/multisig.h +++ b/src/multisig/multisig.h @@ -59,11 +59,14 @@ namespace multisig crypto::public_key &L, crypto::public_key &R); bool generate_multisig_composite_key_image(const cryptonote::account_keys &keys, - 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, - std::size_t real_output_index, - const std::vector &pkis, - crypto::key_image &ki); + 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, + std::size_t real_output_index, + const std::vector &pkis, + crypto::key_image &ki, + const bool use_origin_data, + const cryptonote::origin_data& origin_tx_data + ); } //namespace multisig diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index b2e28aa31..b36a38160 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -58,6 +58,67 @@ namespace multisig { + rct::key sm(rct::key y, int n, const rct::key &x) + { + while (n--) + sc_mul(y.bytes, y.bytes, y.bytes); + sc_mul(y.bytes, y.bytes, x.bytes); + return y; + } + + // Compute the inverse of a scalar, the clever way + rct::key invert(const rct::key &x) + { + rct::key _1, _10, _100, _11, _101, _111, _1001, _1011, _1111; + + _1 = x; + sc_mul(_10.bytes, _1.bytes, _1.bytes); + sc_mul(_100.bytes, _10.bytes, _10.bytes); + sc_mul(_11.bytes, _10.bytes, _1.bytes); + sc_mul(_101.bytes, _10.bytes, _11.bytes); + sc_mul(_111.bytes, _10.bytes, _101.bytes); + sc_mul(_1001.bytes, _10.bytes, _111.bytes); + sc_mul(_1011.bytes, _10.bytes, _1001.bytes); + sc_mul(_1111.bytes, _100.bytes, _1011.bytes); + + rct::key inv; + sc_mul(inv.bytes, _1111.bytes, _1.bytes); + + inv = sm(inv, 123 + 3, _101); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 4, _1001); + inv = sm(inv, 2, _11); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 1 + 3, _101); + inv = sm(inv, 3 + 3, _101); + inv = sm(inv, 3, _111); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 2 + 3, _111); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 1 + 4, _1011); + inv = sm(inv, 2 + 4, _1011); + inv = sm(inv, 6 + 4, _1001); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 3 + 2, _11); + inv = sm(inv, 3 + 2, _11); + inv = sm(inv, 1 + 4, _1001); + inv = sm(inv, 1 + 3, _111); + inv = sm(inv, 2 + 4, _1111); + inv = sm(inv, 1 + 4, _1011); + inv = sm(inv, 3, _101); + inv = sm(inv, 2 + 4, _1111); + inv = sm(inv, 3, _101); + inv = sm(inv, 1 + 2, _11); + + // Sanity check for successful inversion + rct::key tmp; + sc_mul(tmp.bytes, inv.bytes, x.bytes); + CHECK_AND_ASSERT_THROW_MES(tmp == rct::identity(), "invert failed"); + return inv; + } + namespace signing { //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- @@ -108,9 +169,12 @@ static bool compute_keys_for_sources( if (src.real_output >= src.outputs.size()) return false; + /* // Populate this struct if you want to make use of multisig for Salvium!!! assert(false); cryptonote::origin_data origin_tx_data; + */ + bool use_origin_data = (src.origin_tx_data.tx_type != cryptonote::transaction_type::UNSET); if (not cryptonote::generate_key_image_helper( account_keys, @@ -122,8 +186,8 @@ static bool compute_keys_for_sources( tmp_keys, tmp_key_image, hwdev, - true, - origin_tx_data + use_origin_data, + src.origin_tx_data )) { return false; } @@ -589,6 +653,95 @@ static bool try_reconstruct_range_proofs(const int bp_version, return false; } //---------------------------------------------------------------------------------------------------------------------- +static bool set_tx_return_address_information(const cryptonote::account_keys& account_keys, + size_t change_index, + crypto::public_key& txkey_pub, + cryptonote::transaction& unsigned_tx + ) +{ + if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER || unsigned_tx.type == cryptonote::transaction_type::STAKE) { + + // Get the output public key for the change output + crypto::public_key P_change = crypto::null_pkey; + if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER) + CHECK_AND_ASSERT_MES(unsigned_tx.vout.size() == 2, false, "Internal error - incorrect number of outputs (!=2) for TRANSFER tx"); + else if (unsigned_tx.type == cryptonote::transaction_type::STAKE) + CHECK_AND_ASSERT_MES(unsigned_tx.vout.size() == 1, false, "Internal error - incorrect number of outputs (!=1) for YIELD tx"); + CHECK_AND_ASSERT_MES(cryptonote::get_output_public_key(unsigned_tx.vout[change_index], P_change), false, "Internal error - failed to get TX change output public key"); + CHECK_AND_ASSERT_MES(P_change != crypto::null_pkey, false, "Internal error - not found TX change output for TRANSFER tx"); + + // Get the uniqueness for this TX + crypto::ec_scalar y; + struct { + char domain_separator[8]; + crypto::public_key pubkey; + } buf; + std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator)); + std::strncpy(buf.domain_separator, "RETURN", 7); + buf.pubkey = P_change; + crypto::hash_to_scalar(&buf, sizeof(buf), y); + + hw::device& hwdev = account_keys.get_device(); + + // First, we need to produce the multiplicative inverse of the scalar "y" (aka "y^-1") + rct::key key_y = (rct::key&)(y); + rct::key key_inv_y = invert(key_y); + crypto::public_key pk_aP_change = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(P_change), rct::sk2rct(account_keys.m_view_secret_key))); + + // Sanity check that we can reverse the invert safely + rct::key key_aP_change = rct::pk2rct(pk_aP_change); + rct::key key_F = rct::scalarmultKey(key_aP_change, key_inv_y); + rct::key key_verify = rct::scalarmultKey(key_F, key_y); + CHECK_AND_ASSERT_MES(key_verify == key_aP_change, false, "at get_return_address: failed to verify invert() function with smK() approach"); + + if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER) { + + // Store the F point - we do not need to generate a full return address in this instance + unsigned_tx.return_address = rct::rct2pk(key_F); + + // Clear the pubkey, because it isn't used + unsigned_tx.return_pubkey = crypto::null_pkey; + + } else if (unsigned_tx.type == cryptonote::transaction_type::STAKE) { + + // CONVERT / YIELD Semantics + // From this point forward, we are departing from the original "return address" scheme + // We have to derive the full return address and TX pubkey, because PROTOCOL_TX cannot + + // First, create a secret TX key (= s) - this will be lost at the end of this function, but that's OK + crypto::secret_key s = cryptonote::keypair::generate(hw::get_device("default")).sec; + + // Next, calculate the corresponding TX public key (= sP_change) + // This has to be done using smK() call because of g_k_d() performing a torsion clear + unsigned_tx.return_pubkey = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(P_change), rct::sk2rct(s))); + + // Next, calculate a derivation using the TX public key and our secret view key + crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); + bool r = hwdev.generate_key_derivation(unsigned_tx.return_pubkey, account_keys.m_view_secret_key, derivation); + CHECK_AND_ASSERT_MES(r, false, "in get_return_address(): failed to generate_key_derivation(" << unsigned_tx.return_pubkey << ", )"); + + // Finally, calculate the onetime address to be used for returns + crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key); + r = crypto::derive_public_key(derivation, 0, P_change, out_eph_public_key); + CHECK_AND_ASSERT_MES(r, false, "in get_return_address(): failed to derive_public_key(" << derivation << ", " << key_y << ", "<< P_change << ")"); + + // Sanity checks + crypto::public_key P_change_verify = crypto::null_pkey; + r = crypto::derive_subaddress_public_key(out_eph_public_key, derivation, 0, P_change_verify); + CHECK_AND_ASSERT_MES(r, false, "in get_return_address(): failed sanity check derive_subaddress_public_key(" << out_eph_public_key << ", " << derivation << ", " << key_y << ", " << P_change_verify << ")"); + CHECK_AND_ASSERT_MES(P_change == P_change_verify, false, "in get_return_address(): failed sanity check (keys do not match)"); + + // All is well - copy the return address + unsigned_tx.return_address = out_eph_public_key; + + } else { + + assert(false); + } + } + + return true; +} //---------------------------------------------------------------------------------------------------------------------- static bool set_tx_rct_signatures( const std::uint64_t fee, @@ -677,35 +830,36 @@ static bool set_tx_rct_signatures( if (not reconstruction) { a.resize(num_sources); rv.p.pseudoOuts.resize(num_sources); - a[num_sources - 1] = rct::zero(); + rct::key difference = rct::zero(); + rct::key sumpouts = rct::zero(); + rct::key sumouts = rct::zero(); for (std::size_t i = 0; i < num_destinations; ++i) { sc_add( - a[num_sources - 1].bytes, - a[num_sources - 1].bytes, + sumouts.bytes, + sumouts.bytes, output_amount_masks[i].bytes ); } - for (std::size_t i = 0; i < num_sources - 1; ++i) { + for (std::size_t i = 0; i < num_sources; ++i) { rct::skGen(a[i]); - sc_sub( - a[num_sources - 1].bytes, - a[num_sources - 1].bytes, + sc_add( + sumpouts.bytes, + sumpouts.bytes, a[i].bytes ); rct::genC(rv.p.pseudoOuts[i], a[i], sources[i].amount); } - rct::genC( - rv.p.pseudoOuts[num_sources - 1], - a[num_sources - 1], - sources[num_sources - 1].amount - ); + sc_sub(difference.bytes, sumpouts.bytes, sumouts.bytes); + rct::genC(rv.p_r, difference, 0); } // check balance if reconstructing the tx else { rv.p.pseudoOuts = unsigned_tx.rct_signatures.p.pseudoOuts; + rv.p_r = unsigned_tx.rct_signatures.p_r; if (num_sources != rv.p.pseudoOuts.size()) return false; rct::key balance_accumulator = rct::scalarmultH(rct::d2h(fee)); + rct::addKeys(balance_accumulator, balance_accumulator, rv.p_r); for (const auto& e: rv.outPk) rct::addKeys(balance_accumulator, balance_accumulator, e.mask); for (const auto& pseudoOut: rv.p.pseudoOuts) @@ -828,6 +982,7 @@ tx_builder_ringct_t::~tx_builder_ringct_t() bool tx_builder_ringct_t::init( const cryptonote::account_keys& account_keys, const std::vector& extra, + const cryptonote::transaction_type& type, const std::uint64_t unlock_time, const std::uint32_t subaddr_account, const std::set& subaddr_minor_indices, @@ -863,6 +1018,12 @@ bool tx_builder_ringct_t::init( // misc. fields unsigned_tx.version = 2; //rct = 2 unsigned_tx.unlock_time = unlock_time; + unsigned_tx.type = (type == cryptonote::transaction_type::RETURN) ? cryptonote::TRANSFER : type; + unsigned_tx.source_asset_type = "SAL"; + if (type == cryptonote::transaction_type::BURN) + unsigned_tx.destination_asset_type = "BURN"; + else + unsigned_tx.destination_asset_type = "SAL"; // sort inputs sort_sources(sources); @@ -932,6 +1093,29 @@ bool tx_builder_ringct_t::init( if (not set_tx_outputs_result) return false; + if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER || unsigned_tx.type == cryptonote::transaction_type::STAKE) { + + // Identify the change output + bool found_change{false}; + size_t change_idx{0}; + for (size_t idx=0; idx @@ -71,6 +72,7 @@ public: bool init( const cryptonote::account_keys& account_keys, const std::vector& extra, + const cryptonote::transaction_type& type, const std::uint64_t unlock_time, const std::uint32_t subaddr_account, const std::set& subaddr_minor_indices, diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 2f17b891e..2d1df92c3 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -269,6 +269,17 @@ void toJsonValue(rapidjson::Writer& dest, const cryptonote::t INSERT_INTO_JSON_OBJECT(dest, inputs, tx.vin); INSERT_INTO_JSON_OBJECT(dest, outputs, tx.vout); INSERT_INTO_JSON_OBJECT(dest, extra, tx.extra); + INSERT_INTO_JSON_OBJECT(dest, type, static_cast(tx.type)); + if (tx.type != cryptonote::transaction_type::PROTOCOL) { + INSERT_INTO_JSON_OBJECT(dest, amount_burnt, tx.amount_burnt); + if (tx.type != cryptonote::transaction_type::MINER) { + INSERT_INTO_JSON_OBJECT(dest, return_address, tx.return_address); + INSERT_INTO_JSON_OBJECT(dest, return_pubkey, tx.return_pubkey); + INSERT_INTO_JSON_OBJECT(dest, source_asset_type, tx.source_asset_type); + INSERT_INTO_JSON_OBJECT(dest, destination_asset_type, tx.destination_asset_type); + INSERT_INTO_JSON_OBJECT(dest, amount_slippage_limit, tx.amount_slippage_limit); + } + } if (!tx.pruned) { INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures); @@ -291,6 +302,19 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx) GET_FROM_JSON_OBJECT(val, tx.vin, inputs); GET_FROM_JSON_OBJECT(val, tx.vout, outputs); GET_FROM_JSON_OBJECT(val, tx.extra, extra); + uint8_t tx_type = 0; + GET_FROM_JSON_OBJECT(val, tx_type, type); + tx.type = static_cast(tx_type); + if (tx.type != cryptonote::transaction_type::PROTOCOL) { + GET_FROM_JSON_OBJECT(val, tx.amount_burnt, amount_burnt); + if (tx.type != cryptonote::transaction_type::MINER) { + GET_FROM_JSON_OBJECT(val, tx.return_address, return_address); + GET_FROM_JSON_OBJECT(val, tx.return_pubkey, return_pubkey); + GET_FROM_JSON_OBJECT(val, tx.source_asset_type, source_asset_type); + GET_FROM_JSON_OBJECT(val, tx.destination_asset_type, destination_asset_type); + GET_FROM_JSON_OBJECT(val, tx.amount_slippage_limit, amount_slippage_limit); + } + } GET_FROM_JSON_OBJECT(val, tx.rct_signatures, ringct); const auto& sigs = val.FindMember("signatures"); @@ -1138,6 +1162,7 @@ void toJsonValue(rapidjson::Writer& dest, const rct::rctSig& INSERT_INTO_JSON_OBJECT(dest, encrypted, sig.ecdhInfo); INSERT_INTO_JSON_OBJECT(dest, commitments, transform(sig.outPk, just_mask)); INSERT_INTO_JSON_OBJECT(dest, fee, sig.txnFee); + INSERT_INTO_JSON_OBJECT(dest, p_r, sig.p_r); } // prunable @@ -1174,6 +1199,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) GET_FROM_JSON_OBJECT(val, sig.ecdhInfo, encrypted); GET_FROM_JSON_OBJECT(val, sig.outPk, commitments); GET_FROM_JSON_OBJECT(val, sig.txnFee, fee); + GET_FROM_JSON_OBJECT(val, sig.p_r, p_r); } // prunable diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 77f4ad981..d1ab13683 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1691,7 +1691,7 @@ bool simple_wallet::export_raw_multisig(const std::vector &args) for (auto &ptx: txs.m_ptx) { const crypto::hash txid = cryptonote::get_transaction_hash(ptx.tx); - const std::string filename = std::string("raw_multisig_monero_tx_") + epee::string_tools::pod_to_hex(txid); + const std::string filename = std::string("raw_multisig_salvium_tx_") + epee::string_tools::pod_to_hex(txid); if (!filenames.empty()) filenames += ", "; filenames += filename; @@ -3432,7 +3432,7 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::on_command, this, &simple_wallet::sign_transfer, _1), tr(USAGE_SIGN_TRANSFER), tr("Sign a transaction from a file. If the parameter \"export_raw\" is specified, transaction raw hex data suitable for the daemon RPC /sendrawtransaction is exported.\n" - "Use the parameter to specify the file to read from. If not specified, the default \"unsigned_monero_tx\" will be used.")); + "Use the parameter to specify the file to read from. If not specified, the default \"unsigned_salvium_tx\" will be used.")); m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::on_command, this, &simple_wallet::submit_transfer, _1), tr("Submit a signed transaction from a file.")); @@ -7141,7 +7141,7 @@ bool simple_wallet::transfer_main( } else if (m_wallet->multisig()) { - bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); + bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); @@ -7149,7 +7149,7 @@ bool simple_wallet::transfer_main( } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_salvium_tx"; } } else if (m_wallet->get_account().get_device().has_tx_cold_sign()) @@ -7178,7 +7178,7 @@ bool simple_wallet::transfer_main( } else if (m_wallet->watch_only()) { - bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); + bool r = m_wallet->save_tx(ptx_vector, "unsigned_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); @@ -7186,7 +7186,7 @@ bool simple_wallet::transfer_main( } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_salvium_tx"; } } else @@ -7344,26 +7344,26 @@ bool simple_wallet::sweep_unmixable(const std::vector &args_) if (m_wallet->multisig()) { CHECK_MULTISIG_ENABLED(); - bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); + bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_salvium_tx"; } } else if (m_wallet->watch_only()) { - bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); + bool r = m_wallet->save_tx(ptx_vector, "unsigned_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_salvium_tx"; } } else @@ -7652,14 +7652,14 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co if (m_wallet->multisig()) { CHECK_MULTISIG_ENABLED(); - bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); + bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_salvium_tx"; } } else if (m_wallet->get_account().get_device().has_tx_cold_sign()) @@ -7689,14 +7689,14 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co } else if (m_wallet->watch_only()) { - bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); + bool r = m_wallet->save_tx(ptx_vector, "unsigned_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_salvium_tx"; } } else @@ -7887,14 +7887,14 @@ bool simple_wallet::sweep_single(const std::vector &args_) if (m_wallet->multisig()) { CHECK_MULTISIG_ENABLED(); - bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); + bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_salvium_tx"; } } else if (m_wallet->get_account().get_device().has_tx_cold_sign()) @@ -7925,14 +7925,14 @@ bool simple_wallet::sweep_single(const std::vector &args_) } else if (m_wallet->watch_only()) { - bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); + bool r = m_wallet->save_tx(ptx_vector, "unsigned_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_salvium_tx"; } } else @@ -8110,14 +8110,14 @@ bool simple_wallet::return_payment(const std::vector &args_) if (m_wallet->multisig()) { CHECK_MULTISIG_ENABLED(); - bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); + bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_salvium_tx"; } } else if (m_wallet->get_account().get_device().has_tx_cold_sign()) @@ -8152,14 +8152,14 @@ bool simple_wallet::return_payment(const std::vector &args_) } else if (m_wallet->watch_only()) { - bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); + bool r = m_wallet->save_tx(ptx_vector, "unsigned_salvium_tx"); if (!r) { fail_msg_writer() << tr("Failed to write transaction(s) to file"); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx"; + success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_salvium_tx"; } } else @@ -8678,7 +8678,7 @@ bool simple_wallet::sign_transfer(const std::vector &args_) } bool export_raw = false; - std::string unsigned_filename = "unsigned_monero_tx"; + std::string unsigned_filename = "unsigned_salvium_tx"; if (args_.size() > 2 || (args_.size() == 2 && args_[0] != "export_raw")) { PRINT_USAGE(USAGE_SIGN_TRANSFER); @@ -8702,7 +8702,7 @@ bool simple_wallet::sign_transfer(const std::vector &args_) std::vector ptx; try { - bool r = m_wallet->sign_tx(unsigned_filename, "signed_monero_tx", ptx, [&](const tools::wallet2::unsigned_tx_set &tx){ return accept_loaded_tx(tx); }, export_raw); + bool r = m_wallet->sign_tx(unsigned_filename, "signed_salvium_tx", ptx, [&](const tools::wallet2::unsigned_tx_set &tx){ return accept_loaded_tx(tx); }, export_raw); if (!r) { fail_msg_writer() << tr("Failed to sign transaction"); @@ -8722,7 +8722,7 @@ bool simple_wallet::sign_transfer(const std::vector &args_) txids_as_text += (", "); txids_as_text += epee::string_tools::pod_to_hex(get_transaction_hash(t.tx)); } - success_msg_writer(true) << tr("Transaction successfully signed to file ") << "signed_monero_tx" << ", txid " << txids_as_text; + success_msg_writer(true) << tr("Transaction successfully signed to file ") << "signed_salvium_tx" << ", txid " << txids_as_text; if (export_raw) { std::string rawfiles_as_text; @@ -8730,7 +8730,7 @@ bool simple_wallet::sign_transfer(const std::vector &args_) { if (i > 0) rawfiles_as_text += ", "; - rawfiles_as_text += "signed_monero_tx_raw" + (ptx.size() == 1 ? "" : ("_" + std::to_string(i))); + rawfiles_as_text += "signed_salvium_tx_raw" + (ptx.size() == 1 ? "" : ("_" + std::to_string(i))); } success_msg_writer(true) << tr("Transaction raw hex data exported to ") << rawfiles_as_text; } @@ -8750,7 +8750,7 @@ bool simple_wallet::submit_transfer(const std::vector &args_) try { std::vector ptx_vector; - bool r = m_wallet->load_tx("signed_monero_tx", ptx_vector, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); }); + bool r = m_wallet->load_tx("signed_salvium_tx", ptx_vector, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); }); if (!r) { fail_msg_writer() << tr("Failed to load transaction from file"); @@ -11357,7 +11357,7 @@ void simple_wallet::commit_or_save(std::vector& ptx_ cryptonote::blobdata blob; tx_to_blob(ptx.tx, blob); const std::string blob_hex = epee::string_tools::buff_to_hex_nodelimer(blob); - const std::string filename = "raw_monero_tx" + (ptx_vector.size() == 1 ? "" : ("_" + std::to_string(i++))); + const std::string filename = "raw_salvium_tx" + (ptx_vector.size() == 1 ? "" : ("_" + std::to_string(i++))); if (m_wallet->save_to_file(filename, blob_hex, true)) success_msg_writer(true) << tr("Transaction successfully saved to ") << filename << tr(", txid ") << txid; else diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e8fe2b4f8..cd5cb2e4f 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2750,9 +2750,9 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_asset_type(tx.vout[o], asset_type), error::wallet_internal_error, "failed to get output_asset_type"); m_transfers.push_back(transfer_details{}); if (m_transfers_indices.count(asset_type) == 0) { - m_transfers_indices[asset_type] = std::vector{}; + m_transfers_indices[asset_type] = std::set{}; } - m_transfers_indices[asset_type].push_back(m_transfers.size()-1); + m_transfers_indices[asset_type].insert(m_transfers.size()-1); transfer_details& td = m_transfers.back(); td.m_block_height = height; td.m_internal_output_index = o; @@ -8329,6 +8329,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui } // try to find a rct input of enough size - for (size_t& i: m_transfers_indices[asset_type]) + for (size_t i: m_transfers_indices[asset_type]) { const transfer_details& td = m_transfers[i]; if (!is_spent(td, false) && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) @@ -10340,25 +10344,28 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui // this could be made better by picking one of the outputs to be a small one, since those // are less useful since often below the needed money, so if one can be used in a pair, // it gets rid of it for the future - for (size_t i = 0; i < m_transfers_indices[asset_type].size(); i++) + for (auto i=m_transfers_indices[asset_type].begin(); i!= m_transfers_indices[asset_type].end(); ++i) { - size_t idx = m_transfers_indices[asset_type][i]; - const transfer_details& td = m_transfers[i]; + size_t idx = *i; + const transfer_details& td = m_transfers[idx]; if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) { if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below) { - MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]"); + MDEBUG("Ignoring output " << idx << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]"); continue; } - LOG_PRINT_L2("Considering input " << i << ", " << print_money(td.amount())); - for (size_t j = i + 1; j < m_transfers_indices[asset_type].size(); ++j) + LOG_PRINT_L2("Considering input " << idx << ", " << print_money(td.amount())); + if (i == m_transfers_indices[asset_type].end()) continue; + auto j = i; + std::advance(j, 1); + for (; j!=m_transfers_indices[asset_type].end(); ++j) { - size_t idx2 = m_transfers_indices[asset_type][j]; + size_t idx2 = *j; const transfer_details& td2 = m_transfers[idx2]; if (td2.amount() > m_ignore_outputs_above || td2.amount() < m_ignore_outputs_below) { - MDEBUG("Ignoring output " << j << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]"); + MDEBUG("Ignoring output " << idx2 << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]"); continue; } if (!is_spent(td2, false) && !td2.m_frozen && !td2.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index) @@ -10367,16 +10374,16 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui // already found. If the same, don't update, and oldest suitable outputs // will be used in preference. float relatedness = get_output_relatedness(td, td2); - LOG_PRINT_L2(" with input " << j << ", " << print_money(td2.amount()) << ", relatedness " << relatedness); + LOG_PRINT_L2(" with input " << idx2 << ", " << print_money(td2.amount()) << ", relatedness " << relatedness); if (relatedness < current_output_relatdness) { // reset the current picks with those, and return them directly // if they're unrelated. If they are related, we'll end up returning // them if we find nothing better picks.clear(); - picks.push_back(i); - picks.push_back(j); - LOG_PRINT_L0("we could use " << i << " and " << j); + picks.push_back(idx); + picks.push_back(idx2); + LOG_PRINT_L0("we could use " << idx << " and " << idx2); if (relatedness == 0.0f) return picks; current_output_relatdness = relatedness; @@ -10693,7 +10700,7 @@ std::vector wallet2::create_transactions_2(std::vector transfer_container; - typedef serializable_unordered_map> transfer_details_indices; + typedef serializable_unordered_map> transfer_details_indices; typedef serializable_unordered_multimap payment_container; typedef std::set unique_index_container;