From dc4aad7eb5fffa450d4c5eb094cf962e45b2f43a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 15 Jun 2016 23:37:13 +0100 Subject: add rct to the protocol It is not yet constrained to a fork, so don't use on the real network or you'll be orphaned or rejected. --- src/simplewallet/simplewallet.cpp | 56 +++++++++++++++++++++++++++------------ src/simplewallet/simplewallet.h | 7 ++--- 2 files changed, 43 insertions(+), 20 deletions(-) (limited to 'src/simplewallet') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 1840e54c9..78d135451 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -99,6 +99,12 @@ typedef cryptonote::simple_wallet sw; m_auto_refresh_enabled.store(auto_refresh_enabled, std::memory_order_relaxed); \ }) +enum TransferType { + TransferOriginal, + TransferNew, + TransferRingCT, +}; + namespace { const command_line::arg_descriptor arg_wallet_file = {"wallet-file", sw::tr("Use wallet "), ""}; @@ -644,6 +650,7 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), tr("Show blockchain height")); m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1), tr("transfer [] [ ... ] [payment_id] - Transfer ,... to ,... , respectively. is the number of extra inputs to include for untraceability (from 0 to maximum available)")); m_cmd_binder.set_handler("transfer_new", boost::bind(&simple_wallet::transfer_new, this, _1), tr("Same as transfer, but using a new transaction building algorithm")); + m_cmd_binder.set_handler("transfer_rct", boost::bind(&simple_wallet::transfer_rct, this, _1), tr("Same as transfer, but using RingCT transactions")); m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0")); m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("Send all unlocked balance an address")); m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), tr("set_log - Change current log detail level, <0-4>")); @@ -1888,24 +1895,24 @@ void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block m_refresh_progress_reporter.update(height, false); } //---------------------------------------------------------------------------------------------------- -void simple_wallet::on_money_received(uint64_t height, const cryptonote::transaction& tx, size_t out_index) +void simple_wallet::on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount) { message_writer(epee::log_space::console_color_green, false) << "\r" << tr("Height ") << height << ", " << tr("transaction ") << get_transaction_hash(tx) << ", " << - tr("received ") << print_money(tx.vout[out_index].amount); + tr("received ") << print_money(amount); if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); else m_refresh_progress_reporter.update(height, true); } //---------------------------------------------------------------------------------------------------- -void simple_wallet::on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, size_t out_index, const cryptonote::transaction& spend_tx) +void simple_wallet::on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx) { message_writer(epee::log_space::console_color_magenta, false) << "\r" << tr("Height ") << height << ", " << tr("transaction ") << get_transaction_hash(spend_tx) << ", " << - tr("spent ") << print_money(in_tx.vout[out_index].amount); + tr("spent ") << print_money(amount); if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); else @@ -2052,13 +2059,15 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args { if (!transfers_found) { - message_writer() << boost::format("%21s%8s%16s%68s") % tr("amount") % tr("spent") % tr("global index") % tr("tx id"); + message_writer() << boost::format("%21s%8s%12s%8s%16s%68s") % tr("amount") % tr("spent") % tr("unlocked") % tr("ringct") % tr("global index") % tr("tx id"); transfers_found = true; } message_writer(td.m_spent ? epee::log_space::console_color_magenta : epee::log_space::console_color_green, false) << - boost::format("%21s%8s%16u%68s") % + boost::format("%21s%8s%12s%8s%16u%68s") % print_money(td.amount()) % (td.m_spent ? tr("T") : tr("F")) % + (m_wallet->is_transfer_unlocked(td) ? tr("unlocked") : tr("locked")) % + (td.is_rct() ? tr("RingCT") : tr("-")) % td.m_global_output_index % get_transaction_hash (td.m_tx); } @@ -2274,7 +2283,7 @@ bool simple_wallet::get_address_from_str(const std::string &str, cryptonote::acc return true; } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::transfer_main(bool new_algorithm, const std::vector &args_) +bool simple_wallet::transfer_main(int transfer_type, const std::vector &args_) { if (!try_connect_to_daemon()) return true; @@ -2386,10 +2395,20 @@ bool simple_wallet::transfer_main(bool new_algorithm, const std::vector ptx_vector; - if (new_algorithm) - ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); - else - ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + switch (transfer_type) + { + case TransferNew: + ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + break; + default: + LOG_ERROR("Unknown transfer method, using original"); + case TransferOriginal: + ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + break; + case TransferRingCT: + ptx_vector = m_wallet->create_transactions_rct(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + break; + } // if more than one tx necessary, prompt user to confirm if (m_wallet->always_confirm_transfers() || ptx_vector.size() > 1) @@ -2531,14 +2550,18 @@ bool simple_wallet::transfer_main(bool new_algorithm, const std::vector &args_) { - return transfer_main(false, args_); + return transfer_main(TransferOriginal, args_); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::transfer_new(const std::vector &args_) { - return transfer_main(true, args_); + return transfer_main(TransferNew, args_); +} +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::transfer_rct(const std::vector &args_) +{ + return transfer_main(TransferRingCT, args_); } - //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_unmixable(const std::vector &args_) { @@ -3228,9 +3251,8 @@ bool simple_wallet::show_transfers(const std::vector &args_) m_wallet->get_unconfirmed_payments_out(upayments); for (std::list>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) { const tools::wallet2::unconfirmed_transfer_details &pd = i->second; - uint64_t amount = 0; - cryptonote::get_inputs_money_amount(pd.m_tx, amount); - uint64_t fee = amount - get_outs_money_amount(pd.m_tx); + uint64_t amount = pd.m_amount_in; + uint64_t fee = amount - pd.m_amount_out; std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 52a4e150f..91ebb8e6e 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -120,9 +120,10 @@ namespace cryptonote bool show_incoming_transfers(const std::vector &args); bool show_payments(const std::vector &args); bool show_blockchain_height(const std::vector &args); - bool transfer_main(bool new_algorithm, const std::vector &args); + bool transfer_main(int transfer_type, const std::vector &args); bool transfer(const std::vector &args); bool transfer_new(const std::vector &args); + bool transfer_rct(const std::vector &args); bool sweep_all(const std::vector &args); bool sweep_unmixable(const std::vector &args); std::vector> split_amounts( @@ -171,8 +172,8 @@ namespace cryptonote //----------------- i_wallet2_callback --------------------- virtual void on_new_block(uint64_t height, const cryptonote::block& block); - virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, size_t out_index); - virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, size_t out_index, const cryptonote::transaction& spend_tx); + virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount); + virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx); virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx); //---------------------------------------------------------- -- cgit v1.2.3 From 1017a7546065adb21dba6e29783858578ce620c6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 2 Jul 2016 09:35:25 +0100 Subject: wallet: factor transfer_rct code with transfer code The "transfer" simplewallet command is renamed to "transfer_original". "transfer_new" is renamed "transfer", "transfer_rct" is removed, and the new "transfer" now selects rct or non rct transactions based on the current block height. --- src/simplewallet/simplewallet.cpp | 14 +- src/simplewallet/simplewallet.h | 1 - src/wallet/wallet2.cpp | 293 ++++++-------------------------------- src/wallet/wallet2.h | 1 - 4 files changed, 42 insertions(+), 267 deletions(-) (limited to 'src/simplewallet') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 78d135451..c8c440a04 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -102,7 +102,6 @@ typedef cryptonote::simple_wallet sw; enum TransferType { TransferOriginal, TransferNew, - TransferRingCT, }; namespace @@ -648,9 +647,8 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), tr("incoming_transfers [available|unavailable] - Show incoming transfers, all or filtered by availability")); m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), tr("payments [ ... ] - Show payments for given payment ID[s]")); m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), tr("Show blockchain height")); - m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1), tr("transfer [] [ ... ] [payment_id] - Transfer ,... to ,... , respectively. is the number of extra inputs to include for untraceability (from 0 to maximum available)")); - m_cmd_binder.set_handler("transfer_new", boost::bind(&simple_wallet::transfer_new, this, _1), tr("Same as transfer, but using a new transaction building algorithm")); - m_cmd_binder.set_handler("transfer_rct", boost::bind(&simple_wallet::transfer_rct, this, _1), tr("Same as transfer, but using RingCT transactions")); + m_cmd_binder.set_handler("transfer_original", boost::bind(&simple_wallet::transfer, this, _1), tr("transfer [] [ ... ] [payment_id] - Transfer ,... to ,... , respectively. is the number of extra inputs to include for untraceability (from 0 to maximum available)")); + m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("Same as transfer_original, but using a new transaction building algorithm")); m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0")); m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("Send all unlocked balance an address")); m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), tr("set_log - Change current log detail level, <0-4>")); @@ -2405,9 +2403,6 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorcreate_transactions(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); break; - case TransferRingCT: - ptx_vector = m_wallet->create_transactions_rct(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); - break; } // if more than one tx necessary, prompt user to confirm @@ -2558,11 +2553,6 @@ bool simple_wallet::transfer_new(const std::vector &args_) return transfer_main(TransferNew, args_); } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::transfer_rct(const std::vector &args_) -{ - return transfer_main(TransferRingCT, args_); -} -//---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_unmixable(const std::vector &args_) { if (!try_connect_to_daemon()) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 91ebb8e6e..1259b95b0 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -123,7 +123,6 @@ namespace cryptonote bool transfer_main(int transfer_type, const std::vector &args); bool transfer(const std::vector &args); bool transfer_new(const std::vector &args); - bool transfer_rct(const std::vector &args); bool sweep_all(const std::vector &args); bool sweep_unmixable(const std::vector &args); std::vector> split_amounts( diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 3565945d4..2a873d32e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2974,247 +2974,6 @@ void wallet2::transfer_selected_rct(std::vector wallet2::create_transactions_2(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector extra, bool trusted_daemon) -{ - std::vector unused_transfers_indices; - std::vector unused_dust_indices; - uint64_t needed_money; - uint64_t accumulated_fee, accumulated_outputs, accumulated_change; - struct TX { - std::list selected_transfers; - std::vector dsts; - cryptonote::transaction tx; - pending_tx ptx; - size_t bytes; - - void add(const account_public_address &addr, uint64_t amount) { - std::vector::iterator i; - i = std::find_if(dsts.begin(), dsts.end(), [&](const cryptonote::tx_destination_entry &d) { return !memcmp (&d.addr, &addr, sizeof(addr)); }); - if (i == dsts.end()) - dsts.push_back(tx_destination_entry(amount,addr)); - else - i->amount += amount; - } - }; - std::vector txes; - bool adding_fee; // true if new outputs go towards fee, rather than destinations - uint64_t needed_fee, available_for_fee = 0; - uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit(); - - // throw if attempting a transaction with no destinations - THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination); - - fee_multiplier = sanitize_fee_multiplier (fee_multiplier); - - // calculate total amount being sent to all destinations - // throw if total amount overflows uint64_t - needed_money = 0; - BOOST_FOREACH(auto& dt, dsts) - { - THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination); - needed_money += dt.amount; - LOG_PRINT_L2("transfer: adding " << print_money(dt.amount) << ", for a total of " << print_money (needed_money)); - THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, 0, m_testnet); - } - - // throw if attempting a transaction with no money - THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination); - - // gather all our dust and non dust outputs - for (size_t i = 0; i < m_transfers.size(); ++i) - { - const transfer_details& td = m_transfers[i]; - if (!td.m_spent && !td.is_rct() && is_transfer_unlocked(td)) - { - if (is_valid_decomposed_amount(td.amount())) - unused_transfers_indices.push_back(i); - else - unused_dust_indices.push_back(i); - } - } - LOG_PRINT_L2("Starting with " << unused_transfers_indices.size() << " non-dust outputs and " << unused_dust_indices.size() << " dust outputs"); - - // start with an empty tx - txes.push_back(TX()); - accumulated_fee = 0; - accumulated_outputs = 0; - accumulated_change = 0; - adding_fee = false; - needed_fee = 0; - - // while we have something to send - while ((!dsts.empty() && dsts[0].amount > 0) || adding_fee) { - TX &tx = txes.back(); - - // if we need to spend money and don't have any left, we fail - if (unused_dust_indices.empty() && unused_transfers_indices.empty()) { - LOG_PRINT_L2("No more outputs to choose from"); - THROW_WALLET_EXCEPTION_IF(1, error::not_enough_money, unlocked_balance(), needed_money, accumulated_fee + needed_fee); - } - - // get a random unspent output and use it to pay part (or all) of the current destination (and maybe next one, etc) - // This could be more clever, but maybe at the cost of making probabilistic inferences easier - size_t idx = !unused_transfers_indices.empty() ? pop_random_value(unused_transfers_indices) : pop_random_value(unused_dust_indices); - - const transfer_details &td = m_transfers[idx]; - LOG_PRINT_L2("Picking output " << idx << ", amount " << print_money(td.amount())); - - // add this output to the list to spend - tx.selected_transfers.push_back(m_transfers.begin() + idx); - uint64_t available_amount = td.amount(); - accumulated_outputs += available_amount; - - if (adding_fee) - { - LOG_PRINT_L2("We need more fee, adding it to fee"); - available_for_fee += available_amount; - } - else - { - while (!dsts.empty() && dsts[0].amount <= available_amount) - { - // we can fully pay that destination - LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_testnet, dsts[0].addr) << - " for " << print_money(dsts[0].amount)); - tx.add(dsts[0].addr, dsts[0].amount); - available_amount -= dsts[0].amount; - dsts[0].amount = 0; - pop_index(dsts, 0); - } - - if (available_amount > 0 && !dsts.empty()) { - // we can partially fill that destination - LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_testnet, dsts[0].addr) << - " for " << print_money(available_amount) << "/" << print_money(dsts[0].amount)); - tx.add(dsts[0].addr, available_amount); - dsts[0].amount -= available_amount; - available_amount = 0; - } - } - - // here, check if we need to sent tx and start a new one - LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit " - << upper_transaction_size_limit); - bool try_tx; - if (adding_fee) - { - /* might not actually be enough if adding this output bumps size to next kB, but we need to try */ - try_tx = available_for_fee >= needed_fee; - } - else - { - try_tx = dsts.empty() || (tx.selected_transfers.size() * (fake_outs_count+1) * APPROXIMATE_INPUT_BYTES >= TX_SIZE_TARGET(upper_transaction_size_limit)); - } - - if (try_tx) { - cryptonote::transaction test_tx; - pending_tx test_ptx; - - needed_fee = 0; - - LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " << - tx.selected_transfers.size() << " outputs"); - transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, unlock_time, needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); - auto txBlob = t_serializable_object_to_blob(test_ptx.tx); - needed_fee = calculate_fee(txBlob, fee_multiplier); - available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0); - LOG_PRINT_L2("Made a " << txBlob.size() << " kB tx, with " << print_money(available_for_fee) << " available for fee (" << - print_money(needed_fee) << " needed)"); - - if (needed_fee > available_for_fee && dsts[0].amount > 0) - { - // we don't have enough for the fee, but we've only partially paid the current address, - // so we can take the fee from the paid amount, since we'll have to make another tx anyway - std::vector::iterator i; - i = std::find_if(tx.dsts.begin(), tx.dsts.end(), - [&](const cryptonote::tx_destination_entry &d) { return !memcmp (&d.addr, &dsts[0].addr, sizeof(dsts[0].addr)); }); - THROW_WALLET_EXCEPTION_IF(i == tx.dsts.end(), error::wallet_internal_error, "paid address not found in outputs"); - if (i->amount > needed_fee) - { - uint64_t new_paid_amount = i->amount /*+ test_ptx.fee*/ - needed_fee; - LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_testnet, i->addr) << " from " << - print_money(i->amount) << " to " << print_money(new_paid_amount) << " to accomodate " << - print_money(needed_fee) << " fee"); - dsts[0].amount += i->amount - new_paid_amount; - i->amount = new_paid_amount; - test_ptx.fee = needed_fee; - available_for_fee = needed_fee; - } - } - - if (needed_fee > available_for_fee) - { - LOG_PRINT_L2("We could not make a tx, switching to fee accumulation"); - - adding_fee = true; - } - else - { - LOG_PRINT_L2("We made a tx, adjusting fee and saving it"); - transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, unlock_time, needed_fee, extra, - detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); - txBlob = t_serializable_object_to_blob(test_ptx.tx); - LOG_PRINT_L2("Made a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) << - " fee and " << print_money(test_ptx.change_dts.amount) << " change"); - - tx.tx = test_tx; - tx.ptx = test_ptx; - tx.bytes = txBlob.size(); - accumulated_fee += test_ptx.fee; - accumulated_change += test_ptx.change_dts.amount; - adding_fee = false; - if (!dsts.empty()) - { - LOG_PRINT_L2("We have more to pay, starting another tx"); - txes.push_back(TX()); - } - } - } - } - - if (adding_fee) - { - LOG_PRINT_L1("We ran out of outputs while trying to gather final fee"); - THROW_WALLET_EXCEPTION_IF(1, error::not_enough_money, unlocked_balance(), needed_money, accumulated_fee + needed_fee); - } - - LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << - " total fee, " << print_money(accumulated_change) << " total change"); - - std::vector ptx_vector; - for (std::vector::iterator i = txes.begin(); i != txes.end(); ++i) - { - TX &tx = *i; - uint64_t tx_money = 0; - for (std::list::const_iterator mi = tx.selected_transfers.begin(); mi != tx.selected_transfers.end(); ++mi) - tx_money += (*mi)->amount(); - LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() << - ": " << (tx.bytes+1023)/1024 << " kB, sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() << - " outputs to " << tx.dsts.size() << " destination(s), including " << - print_money(tx.ptx.fee) << " fee, " << print_money(tx.ptx.change_dts.amount) << " change"); - ptx_vector.push_back(tx.ptx); - } - - // if we made it this far, we're OK to actually send the transactions - return ptx_vector; -} - static size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs) { size_t size = 0; @@ -3253,7 +3012,22 @@ static size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs) return size; } -std::vector wallet2::create_transactions_rct(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector extra, bool trusted_daemon) +// Another implementation of transaction creation that is hopefully better +// While there is anything left to pay, it goes through random outputs and tries +// to fill the next destination/amount. If it fully fills it, it will use the +// remainder to try to fill the next one as well. +// The tx size if roughly estimated as a linear function of only inputs, and a +// new tx will be created when that size goes above a given fraction of the +// max tx size. At that point, more outputs may be added if the fee cannot be +// satisfied. +// If the next output in the next tx would go to the same destination (ie, we +// cut off at a tx boundary in the middle of paying a given destination), the +// fee will be carved out of the current input if possible, to avoid having to +// add another output just for the fee and getting change. +// This system allows for sending (almost) the entire balance, since it does +// not generate spurious change in all txes, thus decreasing the instantaneous +// usable balance. +std::vector wallet2::create_transactions_2(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector extra, bool trusted_daemon) { std::vector unused_transfers_indices; std::vector unused_dust_indices; @@ -3279,6 +3053,7 @@ std::vector wallet2::create_transactions_rct(std::vector wallet2::create_transactions_rct(std::vector wallet2::create_transactions_rct(std::vector= TX_SIZE_TARGET(upper_transaction_size_limit)); } @@ -3394,8 +3173,12 @@ std::vector wallet2::create_transactions_rct(std::vector wallet2::create_transactions_rct(std::vector= resp_t.result.earliest_height - 10; // start using the rules a bit beforehand if (close_enough) - LOG_PRINT_L2("Using HF1 rules"); + LOG_PRINT_L2("Using v" << (unsigned)version << " rules"); else - LOG_PRINT_L2("Not using HF1 rules"); + LOG_PRINT_L2("Not using v" << (unsigned)version << " rules"); return close_enough; } //---------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 1c835429f..80e8f7f49 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -305,7 +305,6 @@ namespace tools void commit_tx(std::vector& ptx_vector); std::vector create_transactions(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector extra, bool trusted_daemon); std::vector create_transactions_2(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector extra, bool trusted_daemon); - std::vector create_transactions_rct(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector extra, bool trusted_daemon); std::vector create_transactions_all(const cryptonote::account_public_address &address, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector extra, bool trusted_daemon); std::vector create_unmixable_sweep_transactions(bool trusted_daemon); bool check_connection(bool *same_version = NULL); -- cgit v1.2.3 From e81a2b2cfabfb1ad9aaade752a863f1448fc89cd Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 11 Jul 2016 23:14:58 +0100 Subject: port get_tx_key/check_tx_key to rct --- src/cryptonote_core/cryptonote_format_utils.cpp | 18 +++++-- src/cryptonote_core/cryptonote_format_utils.h | 2 +- src/ringct/rctSigs.cpp | 14 +++--- src/ringct/rctSigs.h | 4 +- src/simplewallet/simplewallet.cpp | 63 ++++++++++++++++++++----- src/wallet/wallet2.cpp | 21 +++++++-- src/wallet/wallet2.h | 13 +++-- src/wallet/wallet_rpc_server.cpp | 39 +++++++++++++++ src/wallet/wallet_rpc_server_commands_defs.h | 35 ++++++++++++++ tests/core_tests/rct.cpp | 6 ++- 10 files changed, 181 insertions(+), 34 deletions(-) (limited to 'src/simplewallet') diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 6578776b4..5f8e4024f 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -453,12 +453,13 @@ namespace cryptonote return encrypt_payment_id(payment_id, public_key, secret_key); } //--------------------------------------------------------------- - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct) + bool construct_tx_and_get_tx_keys(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &amount_keys, bool rct) { tx.vin.clear(); tx.vout.clear(); tx.signatures.clear(); tx.rct_signatures = rct::rctSig(); + amount_keys.clear(); tx.version = rct ? 2 : 1; tx.unlock_time = unlock_time; @@ -721,10 +722,18 @@ namespace cryptonote crypto::hash tx_prefix_hash; get_transaction_prefix_hash(tx, tx_prefix_hash); + rct::ctkeyV outSk; if (use_simple_rct) - tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, index); + tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, index, outSk); else - tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, sources[0].real_output); // same index assumption + tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, sources[0].real_output, outSk); // same index assumption + + CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout"); + for (size_t i = 0; i < tx.vout.size(); ++i) + { + amount_keys.push_back(rct::rct2sk(rct::d2h(shuffled_dsts[i].amount))); + amount_keys.push_back(rct::rct2sk(outSk[i].mask)); + } LOG_PRINT2("construct_tx.log", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL, LOG_LEVEL_3); } @@ -735,7 +744,8 @@ namespace cryptonote bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time) { crypto::secret_key tx_key; - return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key); + std::vector amount_keys; + return construct_tx_and_get_tx_keys(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key, amount_keys); } //--------------------------------------------------------------- bool get_inputs_money_amount(const transaction& tx, uint64_t& money) diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h index f4fd8bd34..6dac8e888 100644 --- a/src/cryptonote_core/cryptonote_format_utils.h +++ b/src/cryptonote_core/cryptonote_format_utils.h @@ -74,7 +74,7 @@ namespace cryptonote //--------------------------------------------------------------- bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time); - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &txkey, bool rct = false); + bool construct_tx_and_get_tx_keys(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &amount_keys, bool rct = false); template bool find_tx_extra_field_by_type(const std::vector& tx_extra_fields, T& field) diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 687373fe5..c4a297190 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -535,7 +535,7 @@ namespace rct { // must know the destination private key to find the correct amount, else will return a random number // Note: For txn fees, the last index in the amounts vector should contain that // Thus the amounts vector will be "one" longer than the destinations vectort - rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, unsigned int index) { + rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk) { CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations"); CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing"); for (size_t n = 0; n < mixRing.size(); ++n) { @@ -550,7 +550,7 @@ namespace rct { size_t i = 0; keyV masks(destinations.size()); //sk mask.. - ctkeyV outSk(destinations.size()); + outSk.resize(destinations.size()); for (i = 0; i < destinations.size(); i++) { //add destination to sig rv.outPk[i].dest = copy(destinations[i]); @@ -587,13 +587,14 @@ namespace rct { rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & amounts, const int mixin) { unsigned int index; ctkeyM mixRing; + ctkeyV outSk; tie(mixRing, index) = populateFromBlockchain(inPk, mixin); - return genRct(message, inSk, destinations, amounts, mixRing, index); + return genRct(message, inSk, destinations, amounts, mixRing, index, outSk); } //RCT simple //for post-rct only - rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector &inamounts, const vector &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector & index) { + rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector &inamounts, const vector &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector & index, ctkeyV &outSk) { CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts"); CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk"); CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations"); @@ -612,7 +613,7 @@ namespace rct { size_t i; keyV masks(destinations.size()); //sk mask.. - ctkeyV outSk(destinations.size()); + outSk.resize(destinations.size()); key sumout = zero(); for (i = 0; i < destinations.size(); i++) { @@ -659,12 +660,13 @@ namespace rct { std::vector index; index.resize(inPk.size()); ctkeyM mixRing; + ctkeyV outSk; mixRing.resize(inPk.size()); for (size_t i = 0; i < inPk.size(); ++i) { mixRing[i].resize(mixin+1); index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin); } - return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, index); + return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, index, outSk); } //RingCT protocol diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 94b67f2d9..57f852d68 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -135,10 +135,10 @@ namespace rct { //decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1) // uses the attached ecdh info to find the amounts represented by each output commitment // must know the destination private key to find the correct amount, else will return a random number - rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, unsigned int index); + rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk); rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & amounts, const int mixin); rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & inamounts, const vector & outamounts, xmr_amount txnFee, unsigned int mixin); - rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector & inamounts, const vector & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector & index); + rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector & inamounts, const vector & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector & index, ctkeyV &outSk); bool verRct(const rctSig & rv); bool verRct(const rctSig & rv, const ctkeyM &mixRing, const keyV &II, const key &message); bool verRctSimple(const rctSig & rv); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index c8c440a04..c8fae6edd 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -58,6 +58,7 @@ #include "mnemonics/electrum-words.h" #include "rapidjson/document.h" #include "common/json_util.h" +#include "ringct/rctSigs.h" #include #if defined(WIN32) @@ -2957,15 +2958,18 @@ bool simple_wallet::get_tx_key(const std::vector &args_) LOCK_IDLE_SCOPE(); crypto::secret_key tx_key; - bool r = m_wallet->get_tx_key(txid, tx_key); - if (r) + std::vector amount_keys; + if (m_wallet->get_tx_keys(txid, tx_key, amount_keys)) { - success_msg_writer() << tr("Tx key: ") << tx_key; + std::string s = epee::string_tools::pod_to_hex(tx_key); + for (const auto &k: amount_keys) + s += epee::string_tools::pod_to_hex(k); + success_msg_writer() << tr("Tx key: ") << s; return true; } else { - fail_msg_writer() << tr("no tx key found for this txid"); + fail_msg_writer() << tr("no tx keys found for this txid"); return true; } } @@ -2992,13 +2996,22 @@ bool simple_wallet::check_tx_key(const std::vector &args_) LOCK_IDLE_SCOPE(); - cryptonote::blobdata tx_key_data; - if(!epee::string_tools::parse_hexstr_to_binbuff(local_args[1], tx_key_data)) + if (local_args[1].size() < 64 || local_args[1].size() % 64) { fail_msg_writer() << tr("failed to parse tx key"); return true; } - crypto::secret_key tx_key = *reinterpret_cast(tx_key_data.data()); + std::vector tx_keys; + for (size_t start = 0; start < local_args[1].size(); start += 64) + { + cryptonote::blobdata tx_key_data; + if(!epee::string_tools::parse_hexstr_to_binbuff(std::string(&local_args[1][start], 64), tx_key_data)) + { + fail_msg_writer() << tr("failed to parse tx key"); + return true; + } + tx_keys.push_back(*reinterpret_cast(tx_key_data.data())); + } cryptonote::account_public_address address; bool has_payment_id; @@ -3043,12 +3056,18 @@ bool simple_wallet::check_tx_key(const std::vector &args_) } crypto::key_derivation derivation; - if (!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation)) + if (!crypto::generate_key_derivation(address.m_view_public_key, tx_keys[0], derivation)) { fail_msg_writer() << tr("failed to generate key derivation from supplied parameters"); return true; } + if (tx_keys.size() != tx.vout.size() * 2 + 1) + { + fail_msg_writer() << tr("tx keys don't match tx vout"); + return true; + } + uint64_t received = 0; try { for (size_t n = 0; n < tx.vout.size(); ++n) @@ -3059,13 +3078,33 @@ bool simple_wallet::check_tx_key(const std::vector &args_) crypto::public_key pubkey; derive_public_key(derivation, n, address.m_spend_public_key, pubkey); if (pubkey == tx_out_to_key.key) - received += tx.vout[n].amount; + { + uint64_t amount; + if (tx.version == 1) + { + amount = tx.vout[n].amount; + } + else + { + try + { + rct::key Ctmp; + rct::addKeys2(Ctmp, rct::sk2rct(tx_keys[n * 2 + 2]), rct::sk2rct(tx_keys[n * 2 + 1]), rct::H); + if (rct::equalKeys(tx.rct_signatures.outPk[n].mask, Ctmp)) + amount = rct::h2d(rct::sk2rct(tx_keys[n * 2 + 1])); + else + amount = 0; + } + catch (...) { amount = 0; } + } + received += amount; + } } } - catch(...) + catch(const std::exception &e) { - LOG_ERROR("unknown error"); - fail_msg_writer() << tr("unknown error"); + LOG_ERROR("error: " << e.what()); + fail_msg_writer() << tr("error: ") << e.what(); return true; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a6c9faa80..ef77f68c3 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1258,6 +1258,7 @@ bool wallet2::clear() m_unconfirmed_txs.clear(); m_payments.clear(); m_tx_keys.clear(); + m_amount_keys.clear(); m_confirmed_txs.clear(); m_local_bc_height = 1; return true; @@ -2343,7 +2344,10 @@ void wallet2::commit_tx(pending_tx& ptx) } add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount); if (store_tx_info()) + { m_tx_keys.insert(std::make_pair(txid, ptx.tx_key)); + m_amount_keys.insert(std::make_pair(txid, ptx.amount_keys)); + } LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]"); @@ -2753,7 +2757,8 @@ void wallet2::transfer_selected(const std::vector amount_keys; + bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -2780,6 +2785,7 @@ void wallet2::transfer_selected(const std::vector amount_keys; + bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, dsts, extra, tx, unlock_time, tx_key, amount_keys, true); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -2993,6 +3000,7 @@ void wallet2::transfer_selected_rct(std::vector &outs, size_t num_outputs, } crypto::secret_key tx_key; - bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key); + std::vector amount_keys; + bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -3665,6 +3674,7 @@ void wallet2::transfer_from(const std::vector &outs, size_t num_outputs, ptx.change_dts = change_dts; ptx.selected_transfers = selected_transfers; ptx.tx_key = tx_key; + ptx.amount_keys = amount_keys; ptx.dests = dsts; } @@ -3911,12 +3921,15 @@ std::vector wallet2::create_unmixable_sweep_transactions(bo } } -bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const +bool wallet2::get_tx_keys(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &amount_keys) const { const std::unordered_map::const_iterator i = m_tx_keys.find(txid); if (i == m_tx_keys.end()) return false; tx_key = i->second; + const std::unordered_map>::const_iterator j = m_amount_keys.find(txid); + if (j != m_amount_keys.end()) + amount_keys = j->second; return true; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index ca9d9fb70..c45b64822 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -161,6 +161,7 @@ namespace tools std::list selected_transfers; std::string key_images; crypto::secret_key tx_key; + std::vector amount_keys; std::vector dests; }; @@ -351,6 +352,9 @@ namespace tools if(ver < 13) return; a & m_unconfirmed_payments; + if(ver < 14) + return; + a & m_amount_keys; } /*! @@ -386,7 +390,7 @@ namespace tools bool auto_refresh() const { return m_auto_refresh; } void auto_refresh(bool r) { m_auto_refresh = r; } - bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const; + bool get_tx_keys(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &amount_keys) const; bool use_fork_rules(uint8_t version); @@ -464,6 +468,7 @@ namespace tools std::unordered_map m_confirmed_txs; std::unordered_map m_unconfirmed_payments; std::unordered_map m_tx_keys; + std::unordered_map> m_amount_keys; transfer_container m_transfers; payment_container m_payments; @@ -491,7 +496,7 @@ namespace tools uint64_t m_refresh_from_block_height; }; } -BOOST_CLASS_VERSION(tools::wallet2, 13) +BOOST_CLASS_VERSION(tools::wallet2, 14) BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 2) BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1) BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 4) @@ -795,7 +800,8 @@ namespace tools } crypto::secret_key tx_key; - bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key); + std::vector amount_keys; + bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -821,6 +827,7 @@ namespace tools ptx.change_dts = change_dts; ptx.selected_transfers = selected_transfers; ptx.tx_key = tx_key; + ptx.amount_keys = amount_keys; ptx.dests = dsts; } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 9bcc26077..7d00dde08 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -254,7 +254,16 @@ namespace tools // populate response with tx hash res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx_vector.back().tx)); if (req.get_tx_key) + { res.tx_key = epee::string_tools::pod_to_hex(ptx_vector.back().tx_key); + if (ptx_vector.back().tx.version > 1) + { + for (const auto &i: ptx_vector.back().amount_keys) + { + res.amount_keys.push_back(epee::string_tools::pod_to_hex(i)); + } + } + } return true; } catch (const tools::error::daemon_busy& e) @@ -317,7 +326,17 @@ namespace tools { res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx))); if (req.get_tx_keys) + { res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key)); + res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::key_list()); + if (ptx.tx.version > 1) + { + for (const auto &i: ptx.amount_keys) + { + res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i)); + } + } + } } return true; @@ -363,7 +382,17 @@ namespace tools { res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx))); if (req.get_tx_keys) + { res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key)); + res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_SWEEP_DUST::key_list()); + if (ptx.tx.version > 1) + { + for (const auto &i: ptx.amount_keys) + { + res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i)); + } + } + } } return true; @@ -422,7 +451,17 @@ namespace tools { res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx))); if (req.get_tx_keys) + { res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key)); + res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_SWEEP_ALL::key_list()); + if (ptx.tx.version > 1) + { + for (const auto &i: ptx.amount_keys) + { + res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i)); + } + } + } } return true; diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index d7f01d9ee..ea92a028e 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -132,10 +132,12 @@ namespace wallet_rpc { std::string tx_hash; std::string tx_key; + std::list amount_keys; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash) KV_SERIALIZE(tx_key) + KV_SERIALIZE(amount_keys) END_KV_SERIALIZE_MAP() }; }; @@ -165,14 +167,25 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; + struct key_list + { + std::list keys; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(keys) + END_KV_SERIALIZE_MAP() + }; + struct response { std::list tx_hash_list; std::list tx_key_list; + std::list amount_key_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) KV_SERIALIZE(tx_key_list) + KV_SERIALIZE(amount_key_list) END_KV_SERIALIZE_MAP() }; }; @@ -190,14 +203,25 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; + struct key_list + { + std::list keys; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(keys) + END_KV_SERIALIZE_MAP() + }; + struct response { std::list tx_hash_list; std::list tx_key_list; + std::list amount_key_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) KV_SERIALIZE(tx_key_list) + KV_SERIALIZE(amount_key_list) END_KV_SERIALIZE_MAP() }; }; @@ -225,14 +249,25 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; + struct key_list + { + std::list keys; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(keys) + END_KV_SERIALIZE_MAP() + }; + struct response { std::list tx_hash_list; std::list tx_key_list; + std::list amount_key_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) KV_SERIALIZE(tx_key_list) + KV_SERIALIZE(amount_key_list) END_KV_SERIALIZE_MAP() }; }; diff --git a/tests/core_tests/rct.cpp b/tests/core_tests/rct.cpp index ef5f72fb0..a07c72049 100644 --- a/tests/core_tests/rct.cpp +++ b/tests/core_tests/rct.cpp @@ -116,7 +116,8 @@ bool gen_rct_tx_validation_base::generate_with(std::vector& ev destinations.push_back(td); // 30 -> 7.39 * 4 crypto::secret_key tx_key; - bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), sources, destinations, std::vector(), rct_txes[n], 0, tx_key, true); + std::vector amount_keys; + bool r = construct_tx_and_get_tx_keys(miner_accounts[n].get_keys(), sources, destinations, std::vector(), rct_txes[n], 0, tx_key, amount_keys, true); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); events.push_back(rct_txes[n]); starting_rct_tx_hashes.push_back(get_transaction_hash(rct_txes[n])); @@ -206,7 +207,8 @@ bool gen_rct_tx_validation_base::generate_with(std::vector& ev transaction tx; crypto::secret_key tx_key; - bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), sources, destinations, std::vector(), tx, 0, tx_key, true); + std::vector amount_keys; + bool r = construct_tx_and_get_tx_keys(miner_accounts[0].get_keys(), sources, destinations, std::vector(), tx, 0, tx_key, amount_keys, true); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); if (post_tx) -- cgit v1.2.3 From 9b70856ccb97943249f6e76b19f8abce5cd7aabe Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 24 Jul 2016 17:53:34 +0100 Subject: rct: make the amount key derivable by a third party with the tx key Scheme design from luigi1114. --- src/cryptonote_core/cryptonote_format_utils.cpp | 10 ++---- src/ringct/rctOps.cpp | 20 +++++++---- src/ringct/rctOps.h | 2 ++ src/ringct/rctSigs.cpp | 40 ++++++++++++++------- src/ringct/rctSigs.h | 12 ++++--- src/ringct/rctTypes.h | 2 ++ src/simplewallet/simplewallet.cpp | 40 +++++++++------------ src/wallet/wallet2.cpp | 47 +++++++++++++++++-------- src/wallet/wallet2.h | 4 +-- tests/core_tests/rct.cpp | 8 ++--- tests/unit_tests/ringct.cpp | 43 ++++++++++++++-------- tests/unit_tests/serialization.cpp | 4 ++- 12 files changed, 140 insertions(+), 92 deletions(-) (limited to 'src/simplewallet') diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index e0d8d9d08..ee9a00803 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -681,6 +681,7 @@ namespace cryptonote destinations.push_back(rct::pk2rct(boost::get(tx.vout[i].target).key)); outamounts.push_back(tx.vout[i].amount); amount_out += tx.vout[i].amount; + amount_keys.push_back(rct::rct2sk(rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(shuffled_dsts[i].addr.m_view_public_key), rct::sk2rct(txkey.sec))))); } if (use_simple_rct) @@ -724,16 +725,11 @@ namespace cryptonote get_transaction_prefix_hash(tx, tx_prefix_hash); rct::ctkeyV outSk; if (use_simple_rct) - tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, index, outSk); + tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, (const rct::keyV&)amount_keys, index, outSk); else - tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, sources[0].real_output, outSk); // same index assumption + tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, (const rct::keyV&)amount_keys, sources[0].real_output, outSk); // same index assumption CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout"); - for (size_t i = 0; i < tx.vout.size(); ++i) - { - amount_keys.push_back(rct::rct2sk(rct::d2h(shuffled_dsts[i].amount))); - amount_keys.push_back(rct::rct2sk(outSk[i].mask)); - } LOG_PRINT2("construct_tx.log", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL, LOG_LEVEL_3); } diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index 06267fd8e..b8a0d26ad 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -741,22 +741,28 @@ void fe_mul(fe h,const fe f,const fe g) //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a // where C= aG + bH + void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1) { + key sharedSec2 = hash_to_scalar(sharedSec1); + //encode + sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes); + sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes); + } void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk) { key esk; //compute shared secret skpkGen(esk, unmasked.senderPk); key sharedSec1 = hash_to_scalar(scalarmultKey(receiverPk, esk)); + ecdhEncodeFromSharedSecret(unmasked, sharedSec1); + } + void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1) { key sharedSec2 = hash_to_scalar(sharedSec1); - //encode - sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes); - sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes); + //decode + sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes); + sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes); } void ecdhDecode(ecdhTuple & masked, const key & receiverSk) { //compute shared secret key sharedSec1 = hash_to_scalar(scalarmultKey(masked.senderPk, receiverSk)); - key sharedSec2 = hash_to_scalar(sharedSec1); - //encode - sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes); - sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes); + ecdhDecodeFromSharedSecret(masked, sharedSec1); } } diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h index 6438a1f03..225c5abb9 100644 --- a/src/ringct/rctOps.h +++ b/src/ringct/rctOps.h @@ -165,7 +165,9 @@ namespace rct { //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a // where C= aG + bH + void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1); void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk); + void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1); void ecdhDecode(ecdhTuple & masked, const key & receiverSk); } #endif /* RCTOPS_H */ diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index fa9c833dd..0d4fbee1a 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -535,7 +535,7 @@ namespace rct { // must know the destination private key to find the correct amount, else will return a random number // Note: For txn fees, the last index in the amounts vector should contain that // Thus the amounts vector will be "one" longer than the destinations vectort - rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk) { + rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk) { CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations"); CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing"); for (size_t n = 0; n < mixRing.size(); ++n) { @@ -563,7 +563,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(amounts[i]); - ecdhEncode(rv.ecdhInfo[i], destinations[i]); + ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]); } @@ -584,17 +584,17 @@ namespace rct { return rv; } - rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & amounts, const int mixin) { + rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & amounts, const keyV &amount_keys, const int mixin) { unsigned int index; ctkeyM mixRing; ctkeyV outSk; tie(mixRing, index) = populateFromBlockchain(inPk, mixin); - return genRct(message, inSk, destinations, amounts, mixRing, index, outSk); + return genRct(message, inSk, destinations, amounts, mixRing, amount_keys, index, outSk); } //RCT simple //for post-rct only - rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector &inamounts, const vector &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector & index, ctkeyV &outSk) { + rctSig genRctSimple(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector &inamounts, const vector &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector & index, ctkeyV &outSk) { CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts"); CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk"); CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations"); @@ -630,7 +630,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(outamounts[i]); - ecdhEncode(rv.ecdhInfo[i], destinations[i]); + ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]); } //set txn fee @@ -656,7 +656,7 @@ namespace rct { return rv; } - rctSig genRctSimple(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector &inamounts, const vector &outamounts, xmr_amount txnFee, unsigned int mixin) { + rctSig genRctSimple(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector &inamounts, const vector &outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin) { std::vector index; index.resize(inPk.size()); ctkeyM mixRing; @@ -666,7 +666,7 @@ namespace rct { mixRing[i].resize(mixin+1); index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin); } - return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, index, outSk); + return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk); } //RingCT protocol @@ -782,7 +782,7 @@ namespace rct { //decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1) // uses the attached ecdh info to find the amounts represented by each output commitment // must know the destination private key to find the correct amount, else will return a random number - xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) { + static xmr_amount decodeRctMain(const rctSig & rv, const key & sk, unsigned int i, key & mask, void (*decode)(ecdhTuple&, const key&)) { CHECK_AND_ASSERT_MES(!rv.simple, false, "decodeRct called on simple rctSig"); CHECK_AND_ASSERT_THROW_MES(rv.rangeSigs.size() > 0, "Empty rv.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.rangeSigs"); @@ -790,7 +790,7 @@ namespace rct { //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - ecdhDecode(ecdh_info, sk); + (*decode)(ecdh_info, sk); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; @@ -806,12 +806,20 @@ namespace rct { return h2d(amount); } + xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) { + return decodeRctMain(rv, sk, i, mask, &ecdhDecode); + } + + xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask) { + return decodeRctMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret); + } + xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i) { key mask; return decodeRct(rv, sk, i, mask); } - xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) { + static xmr_amount decodeRctSimpleMain(const rctSig & rv, const key & sk, unsigned int i, key &mask, void (*decode)(ecdhTuple &ecdh, const key&)) { CHECK_AND_ASSERT_MES(rv.simple, false, "decodeRct called on non simple rctSig"); CHECK_AND_ASSERT_THROW_MES(rv.rangeSigs.size() > 0, "Empty rv.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.rangeSigs"); @@ -819,7 +827,7 @@ namespace rct { //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - ecdhDecode(ecdh_info, sk); + (*decode)(ecdh_info, sk); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; @@ -835,6 +843,14 @@ namespace rct { return h2d(amount); } + xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) { + return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecode); + } + + xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key &mask) { + return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret); + } + xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i) { key mask; return decodeRctSimple(rv, sk, i, mask); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index 2064962c3..d150e7180 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -135,18 +135,20 @@ namespace rct { //decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1) // uses the attached ecdh info to find the amounts represented by each output commitment // must know the destination private key to find the correct amount, else will return a random number - rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, unsigned int index, ctkeyV &outSk); - rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & amounts, const int mixin); - rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & inamounts, const vector & outamounts, xmr_amount txnFee, unsigned int mixin); - rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector & inamounts, const vector & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const std::vector & index, ctkeyV &outSk); + rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk); + rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & amounts, const keyV &amount_keys, const int mixin); + rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector & inamounts, const vector & outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin); + rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const vector & inamounts, const vector & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector & index, ctkeyV &outSk); bool verRct(const rctSig & rv); bool verRct(const rctSig & rv, const ctkeyM &mixRing, const keyV &II, const ctkeyV &outPk, const key &message); bool verRctSimple(const rctSig & rv); bool verRctSimple(const rctSig & rv, const ctkeyM &mixRing, const std::vector *II, const ctkeyV &outPk, const key &message); xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask); + xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask); xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i); - xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i); + xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask); xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask); + xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i); } #endif /* RCTSIGS_H */ diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 7e31f679d..d36d3f1b1 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -341,6 +341,8 @@ namespace rct { namespace cryptonote { static inline bool operator==(const crypto::public_key &k0, const rct::key &k1) { return !memcmp(&k0, &k1, 32); } static inline bool operator!=(const crypto::public_key &k0, const rct::key &k1) { return memcmp(&k0, &k1, 32); } + static inline bool operator==(const crypto::secret_key &k0, const rct::key &k1) { return !memcmp(&k0, &k1, 32); } + static inline bool operator!=(const crypto::secret_key &k0, const rct::key &k1) { return memcmp(&k0, &k1, 32); } } template std::ostream &print256(std::ostream &o, const T &v); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index c8fae6edd..709990c7c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2959,12 +2959,9 @@ bool simple_wallet::get_tx_key(const std::vector &args_) crypto::secret_key tx_key; std::vector amount_keys; - if (m_wallet->get_tx_keys(txid, tx_key, amount_keys)) + if (m_wallet->get_tx_key(txid, tx_key)) { - std::string s = epee::string_tools::pod_to_hex(tx_key); - for (const auto &k: amount_keys) - s += epee::string_tools::pod_to_hex(k); - success_msg_writer() << tr("Tx key: ") << s; + success_msg_writer() << tr("Tx key: ") << epee::string_tools::pod_to_hex(tx_key); return true; } else @@ -3001,17 +2998,14 @@ bool simple_wallet::check_tx_key(const std::vector &args_) fail_msg_writer() << tr("failed to parse tx key"); return true; } - std::vector tx_keys; - for (size_t start = 0; start < local_args[1].size(); start += 64) + crypto::secret_key tx_key; + cryptonote::blobdata tx_key_data; + if(!epee::string_tools::parse_hexstr_to_binbuff(local_args[1], tx_key_data)) { - cryptonote::blobdata tx_key_data; - if(!epee::string_tools::parse_hexstr_to_binbuff(std::string(&local_args[1][start], 64), tx_key_data)) - { - fail_msg_writer() << tr("failed to parse tx key"); - return true; - } - tx_keys.push_back(*reinterpret_cast(tx_key_data.data())); + fail_msg_writer() << tr("failed to parse tx key"); + return true; } + tx_key = *reinterpret_cast(tx_key_data.data()); cryptonote::account_public_address address; bool has_payment_id; @@ -3056,18 +3050,12 @@ bool simple_wallet::check_tx_key(const std::vector &args_) } crypto::key_derivation derivation; - if (!crypto::generate_key_derivation(address.m_view_public_key, tx_keys[0], derivation)) + if (!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation)) { fail_msg_writer() << tr("failed to generate key derivation from supplied parameters"); return true; } - if (tx_keys.size() != tx.vout.size() * 2 + 1) - { - fail_msg_writer() << tr("tx keys don't match tx vout"); - return true; - } - uint64_t received = 0; try { for (size_t n = 0; n < tx.vout.size(); ++n) @@ -3089,9 +3077,13 @@ bool simple_wallet::check_tx_key(const std::vector &args_) try { rct::key Ctmp; - rct::addKeys2(Ctmp, rct::sk2rct(tx_keys[n * 2 + 2]), rct::sk2rct(tx_keys[n * 2 + 1]), rct::H); - if (rct::equalKeys(tx.rct_signatures.outPk[n].mask, Ctmp)) - amount = rct::h2d(rct::sk2rct(tx_keys[n * 2 + 1])); + rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key))); + rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n]; + rct::ecdhDecodeFromSharedSecret(ecdh_info, amount_key); + rct::key C = tx.rct_signatures.outPk[n].mask; + rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H); + if (rct::equalKeys(C, Ctmp)) + amount = rct::h2d(ecdh_info.amount); else amount = 0; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 70f9043f0..69063e780 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -195,10 +195,18 @@ void wallet2::check_acc_out(const account_keys &acc, const tx_out &o, const cryp //---------------------------------------------------------------------------------------------------- static uint64_t decodeRct(const rct::rctSig & rv, const rct::key & sk, unsigned int i, rct::key & mask) { - if (rv.simple) - return rct::decodeRctSimple(rv, sk, i, mask); - else - return rct::decodeRct(rv, sk, i, mask); + try + { + if (rv.simple) + return rct::decodeRctSimpleFromSharedSecret(rv, sk, i, mask); + else + return rct::decodeRctFromSharedSecret(rv, sk, i, mask); + } + catch (const std::exception &e) + { + LOG_ERROR("Failed to decode input " << i); + return 0; + } } //---------------------------------------------------------------------------------------------------- void wallet2::process_new_transaction(const cryptonote::transaction& tx, const std::vector &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool) @@ -260,7 +268,11 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s outs.push_back(0); if (money_transfered == 0) - money_transfered = tools::decodeRct(tx.rct_signatures, rct::sk2rct(in_ephemeral[0].sec), 0, mask[0]); + { + const cryptonote::account_keys& keys = m_account.get_keys(); + rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); + money_transfered = tools::decodeRct(tx.rct_signatures, amount_key, 0, mask[0]); + } amount[0] = money_transfered; tx_money_got_in_outs = money_transfered; ++num_vouts_received; @@ -300,7 +312,11 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s outs.push_back(i); if (money_transfered[i] == 0) - money_transfered[i] = tools::decodeRct(tx.rct_signatures, rct::sk2rct(in_ephemeral[i].sec), i, mask[i]); + { + const cryptonote::account_keys& keys = m_account.get_keys(); + rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); + money_transfered[i] = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]); + } tx_money_got_in_outs += money_transfered[i]; amount[i] = money_transfered[i]; ++num_vouts_received; @@ -345,7 +361,11 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s outs.push_back(i); if (money_transfered[i] == 0) - money_transfered[i] = tools::decodeRct(tx.rct_signatures, rct::sk2rct(in_ephemeral[i].sec), i, mask[i]); + { + const cryptonote::account_keys& keys = m_account.get_keys(); + rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); + money_transfered[i] = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]); + } tx_money_got_in_outs += money_transfered[i]; amount[i] = money_transfered[i]; ++num_vouts_received; @@ -374,7 +394,11 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s outs.push_back(i); if (money_transfered == 0) - money_transfered = tools::decodeRct(tx.rct_signatures, rct::sk2rct(in_ephemeral[i].sec), i, mask[i]); + { + const cryptonote::account_keys& keys = m_account.get_keys(); + rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); + money_transfered = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]); + } amount[i] = money_transfered; tx_money_got_in_outs += money_transfered; ++num_vouts_received; @@ -1270,7 +1294,6 @@ bool wallet2::clear() m_unconfirmed_txs.clear(); m_payments.clear(); m_tx_keys.clear(); - m_amount_keys.clear(); m_confirmed_txs.clear(); m_local_bc_height = 1; return true; @@ -2429,7 +2452,6 @@ void wallet2::commit_tx(pending_tx& ptx) if (store_tx_info()) { m_tx_keys.insert(std::make_pair(txid, ptx.tx_key)); - m_amount_keys.insert(std::make_pair(txid, ptx.amount_keys)); } LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]"); @@ -3974,15 +3996,12 @@ std::vector wallet2::create_unmixable_sweep_transactions(bo } } -bool wallet2::get_tx_keys(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &amount_keys) const +bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const { const std::unordered_map::const_iterator i = m_tx_keys.find(txid); if (i == m_tx_keys.end()) return false; tx_key = i->second; - const std::unordered_map>::const_iterator j = m_amount_keys.find(txid); - if (j != m_amount_keys.end()) - amount_keys = j->second; return true; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 2631f630b..3be46882a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -354,7 +354,6 @@ namespace tools a & m_unconfirmed_payments; if(ver < 14) return; - a & m_amount_keys; } /*! @@ -390,7 +389,7 @@ namespace tools bool auto_refresh() const { return m_auto_refresh; } void auto_refresh(bool r) { m_auto_refresh = r; } - bool get_tx_keys(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &amount_keys) const; + bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const; bool use_fork_rules(uint8_t version); @@ -471,7 +470,6 @@ namespace tools std::unordered_map m_confirmed_txs; std::unordered_map m_unconfirmed_payments; std::unordered_map m_tx_keys; - std::unordered_map> m_amount_keys; transfer_container m_transfers; payment_container m_payments; diff --git a/tests/core_tests/rct.cpp b/tests/core_tests/rct.cpp index a07c72049..8dbf8b272 100644 --- a/tests/core_tests/rct.cpp +++ b/tests/core_tests/rct.cpp @@ -125,13 +125,11 @@ bool gen_rct_tx_validation_base::generate_with(std::vector& ev crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(rct_txes[n]); for (size_t o = 0; o < 4; ++o) { - cryptonote::keypair in_ephemeral; - crypto::key_image ki; - cryptonote::generate_key_image_helper(miner_accounts[n].get_keys(), tx_pub_key, o, in_ephemeral, ki); + rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(tx_pub_key), rct::sk2rct(miner_accounts[n].get_keys().m_view_secret_key))); if (rct_txes[n].rct_signatures.simple) - rct::decodeRctSimple(rct_txes[n].rct_signatures, rct::sk2rct(in_ephemeral.sec), o, rct_tx_masks[o+n*4]); + rct::decodeRctSimpleFromSharedSecret(rct_txes[n].rct_signatures, amount_key, o, rct_tx_masks[o+n*4]); else - rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(in_ephemeral.sec), o, rct_tx_masks[o+n*4]); + rct::decodeRctFromSharedSecret(rct_txes[n].rct_signatures, amount_key, o, rct_tx_masks[o+n*4]); } CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes[n], blk_last, miner_account, diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 7970fedb4..81a63b502 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -171,10 +171,12 @@ TEST(ringct, range_proofs) sc.push_back(sctmp); pc.push_back(pctmp); vectoramounts; - + rct::keyV amount_keys; + key mask; //add output 500 amounts.push_back(500); + amount_keys.push_back(rct::hash_to_scalar(rct::zero())); keyV destinations; key Sk, Pk; skpkGen(Sk, Pk); @@ -183,17 +185,18 @@ TEST(ringct, range_proofs) //add output for 12500 amounts.push_back(12500); + amount_keys.push_back(rct::hash_to_scalar(rct::zero())); skpkGen(Sk, Pk); destinations.push_back(Pk); //compute rct data with mixin 500 - rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, 3); + rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3); //verify rct data ASSERT_TRUE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRct(s, Sk, 1)); + ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); // Ring CT with failing MG sig part should not verify! // Since sum of inputs != outputs @@ -204,13 +207,13 @@ TEST(ringct, range_proofs) //compute rct data with mixin 500 - s = genRct(rct::zero(), sc, pc, destinations, amounts, 3); + s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3); //verify rct data ASSERT_FALSE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRct(s, Sk, 1)); + ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); } TEST(ringct, range_proofs_with_fee) @@ -229,10 +232,12 @@ TEST(ringct, range_proofs_with_fee) sc.push_back(sctmp); pc.push_back(pctmp); vectoramounts; - + keyV amount_keys; + key mask; //add output 500 amounts.push_back(500); + amount_keys.push_back(rct::hash_to_scalar(rct::zero())); keyV destinations; key Sk, Pk; skpkGen(Sk, Pk); @@ -241,20 +246,22 @@ TEST(ringct, range_proofs_with_fee) //add txn fee for 1 //has no corresponding destination.. amounts.push_back(1); + amount_keys.push_back(hash_to_scalar(zero())); //add output for 12500 amounts.push_back(12500); + amount_keys.push_back(hash_to_scalar(zero())); skpkGen(Sk, Pk); destinations.push_back(Pk); //compute rct data with mixin 500 - rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, 3); + rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3); //verify rct data ASSERT_TRUE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRct(s, Sk, 1)); + ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); // Ring CT with failing MG sig part should not verify! // Since sum of inputs != outputs @@ -265,13 +272,13 @@ TEST(ringct, range_proofs_with_fee) //compute rct data with mixin 500 - s = genRct(rct::zero(), sc, pc, destinations, amounts, 3); + s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3); //verify rct data ASSERT_FALSE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRct(s, Sk, 1)); + ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); } TEST(ringct, simple) @@ -284,6 +291,8 @@ TEST(ringct, simple) vectorinamounts; //this keyV corresponds to destination pubkeys keyV destinations; + keyV amount_keys; + key mask; //add fake input 3000 //the sc is secret data @@ -303,6 +312,7 @@ TEST(ringct, simple) //add output 5000 outamounts.push_back(5000); + amount_keys.push_back(rct::hash_to_scalar(rct::zero())); //add the corresponding destination pubkey key Sk, Pk; skpkGen(Sk, Pk); @@ -310,6 +320,7 @@ TEST(ringct, simple) //add output 999 outamounts.push_back(999); + amount_keys.push_back(rct::hash_to_scalar(rct::zero())); //add the corresponding destination pubkey skpkGen(Sk, Pk); destinations.push_back(Pk); @@ -319,13 +330,13 @@ TEST(ringct, simple) //compute sig with mixin 2 xmr_amount txnfee = 1; - rctSig s = genRctSimple(message, sc, pc, destinations,inamounts, outamounts, txnfee, 2); + rctSig s = genRctSimple(message, sc, pc, destinations,inamounts, outamounts, amount_keys, txnfee, 2); //verify ring ct signature ASSERT_TRUE(verRctSimple(s)); //decode received amount corresponding to output pubkey index 1 - ASSERT_TRUE(decodeRctSimple(s, Sk, 1)); + ASSERT_TRUE(decodeRctSimpleFromSharedSecret(s, amount_keys[1], 1, mask)); } static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], bool last_is_fee) @@ -334,6 +345,7 @@ static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amount ctkey sctmp, pctmp; vectoramounts; keyV destinations; + keyV amount_keys; key Sk, Pk; for (int n = 0; n < n_inputs; ++n) { @@ -344,12 +356,13 @@ static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amount for (int n = 0; n < n_outputs; ++n) { amounts.push_back(output_amounts[n]); + amount_keys.push_back(rct::hash_to_scalar(rct::zero())); skpkGen(Sk, Pk); if (n < n_outputs - 1 || !last_is_fee) destinations.push_back(Pk); } - return genRct(rct::zero(), sc, pc, destinations, amounts, 3);; + return genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3);; } static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], uint64_t fee) @@ -358,6 +371,7 @@ static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input ctkey sctmp, pctmp; vector inamounts, outamounts; keyV destinations; + keyV amount_keys; key Sk, Pk; for (int n = 0; n < n_inputs; ++n) { @@ -369,11 +383,12 @@ static rct::rctSig make_sample_simple_rct_sig(int n_inputs, const uint64_t input for (int n = 0; n < n_outputs; ++n) { outamounts.push_back(output_amounts[n]); + amount_keys.push_back(hash_to_scalar(zero())); skpkGen(Sk, Pk); destinations.push_back(Pk); } - return genRctSimple(rct::zero(), sc, pc, destinations, inamounts, outamounts, fee, 3);; + return genRctSimple(rct::zero(), sc, pc, destinations, inamounts, outamounts, amount_keys, fee, 3);; } static bool range_proof_test(bool expected_valid, diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index 380c2140f..0a53aeae0 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -554,6 +554,7 @@ TEST(Serialization, serializes_ringct_types) sc.push_back(sctmp); pc.push_back(pctmp); vector amounts; + rct::keyV amount_keys; //add output 500 amounts.push_back(500); rct::keyV destinations; @@ -562,10 +563,11 @@ TEST(Serialization, serializes_ringct_types) destinations.push_back(Pk); //add output for 12500 amounts.push_back(12500); + amount_keys.push_back(rct::hash_to_scalar(rct::zero())); rct::skpkGen(Sk, Pk); destinations.push_back(Pk); //compute rct data with mixin 500 - s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, 3); + s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, 3); mg0 = s0.MG; ASSERT_TRUE(serialization::dump_binary(mg0, blob)); -- cgit v1.2.3 From cc85cc6a3f70a8b22a766779256e75872f2c37a5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 24 Jul 2016 18:00:43 +0100 Subject: simplewallet: better check_tx_key feedback Print number of confirmations if the tx is in the blockchain, or a warning if it's in the pool. --- src/simplewallet/simplewallet.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/simplewallet') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 709990c7c..35469226e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3020,14 +3020,14 @@ bool simple_wallet::check_tx_key(const std::vector &args_) COMMAND_RPC_GET_TRANSACTIONS::response res; req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); if (!net_utils::invoke_http_json_remote_command2(m_daemon_address + "/gettransactions", req, res, m_http_client) || - (res.txs.empty() && res.txs_as_hex.empty())) + (res.txs.size() != 1 && res.txs_as_hex.size() != 1)) { fail_msg_writer() << tr("failed to get transaction from daemon"); return true; } cryptonote::blobdata tx_data; bool ok; - if (!res.txs.empty()) + if (res.txs.size() == 1) ok = string_tools::parse_hexstr_to_binbuff(res.txs.front().as_hex, tx_data); else ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data); @@ -3108,6 +3108,24 @@ bool simple_wallet::check_tx_key(const std::vector &args_) { fail_msg_writer() << get_account_address_as_str(m_wallet->testnet(), address) << " " << tr("received nothing in txid") << " " << txid; } + if (res.txs.front().in_pool) + { + success_msg_writer() << tr("WARNING: this transaction is not yet included in the blockchain!"); + } + else + { + std::string err; + uint64_t bc_height = get_daemon_blockchain_height(err); + if (err.empty()) + { + uint64_t confirmations = bc_height - (res.txs.front().block_height + 1); + success_msg_writer() << boost::format(tr("This transaction has %u confirmations")) % confirmations; + } + else + { + success_msg_writer() << tr("WARNING: failed to determine number of confirmations!"); + } + } return true; } -- cgit v1.2.3 From a47ceee83b0e04a3c440d9ca5a75cf0ac1d9256e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 6 Aug 2016 19:19:25 +0100 Subject: wallet: do not store signatures in the wallet cache Saves some substantial space. Also avoid calculating tx hashes we don't need. --- src/cryptonote_core/cryptonote_basic.h | 2 +- .../cryptonote_boost_serialization.h | 10 ++++ src/cryptonote_core/cryptonote_format_utils.cpp | 5 ++ src/cryptonote_core/cryptonote_format_utils.h | 1 + src/simplewallet/simplewallet.cpp | 2 +- src/wallet/api/transaction_history.cpp | 5 +- src/wallet/wallet2.cpp | 57 +++++++++++++++------- src/wallet/wallet2.h | 35 ++++++++++--- src/wallet/wallet_rpc_server.cpp | 2 +- tests/functional_tests/transactions_flow_test.cpp | 2 +- tests/unit_tests/output_selection.cpp | 5 ++ 11 files changed, 95 insertions(+), 31 deletions(-) (limited to 'src/simplewallet') diff --git a/src/cryptonote_core/cryptonote_basic.h b/src/cryptonote_core/cryptonote_basic.h index afe785eb9..e5a5cc6f5 100644 --- a/src/cryptonote_core/cryptonote_basic.h +++ b/src/cryptonote_core/cryptonote_basic.h @@ -180,7 +180,7 @@ namespace cryptonote FIELD(extra) END_SERIALIZE() - protected: + public: transaction_prefix(){} }; diff --git a/src/cryptonote_core/cryptonote_boost_serialization.h b/src/cryptonote_core/cryptonote_boost_serialization.h index f222db94e..41f864803 100644 --- a/src/cryptonote_core/cryptonote_boost_serialization.h +++ b/src/cryptonote_core/cryptonote_boost_serialization.h @@ -143,6 +143,16 @@ namespace boost } + template + inline void serialize(Archive &a, cryptonote::transaction_prefix &x, const boost::serialization::version_type ver) + { + a & x.version; + a & x.unlock_time; + a & x.vin; + a & x.vout; + a & x.extra; + } + template inline void serialize(Archive &a, cryptonote::transaction &x, const boost::serialization::version_type ver) { diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index ee9a00803..ddcab4f05 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -321,6 +321,11 @@ namespace cryptonote return pub_key_field.pub_key; } //--------------------------------------------------------------- + crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx_prefix) + { + return get_tx_pub_key_from_extra(tx_prefix.extra); + } + //--------------------------------------------------------------- crypto::public_key get_tx_pub_key_from_extra(const transaction& tx) { return get_tx_pub_key_from_extra(tx.extra); diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h index 6dac8e888..e0ffbed67 100644 --- a/src/cryptonote_core/cryptonote_format_utils.h +++ b/src/cryptonote_core/cryptonote_format_utils.h @@ -89,6 +89,7 @@ namespace cryptonote bool parse_tx_extra(const std::vector& tx_extra, std::vector& tx_extra_fields); crypto::public_key get_tx_pub_key_from_extra(const std::vector& tx_extra); + crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx); crypto::public_key get_tx_pub_key_from_extra(const transaction& tx); bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key); bool add_extra_nonce_to_tx_extra(std::vector& tx_extra, const blobdata& extra_nonce); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 35469226e..9e7341451 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2068,7 +2068,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args (m_wallet->is_transfer_unlocked(td) ? tr("unlocked") : tr("locked")) % (td.is_rct() ? tr("RingCT") : tr("-")) % td.m_global_output_index % - get_transaction_hash (td.m_tx); + td.m_txid; } } diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index db42e2141..95aafb04f 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -165,9 +165,8 @@ void TransactionHistoryImpl::refresh() for (std::list>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) { const tools::wallet2::unconfirmed_transfer_details &pd = i->second; const crypto::hash &hash = i->first; - uint64_t amount = 0; - cryptonote::get_inputs_money_amount(pd.m_tx, amount); - uint64_t fee = amount - get_outs_money_amount(pd.m_tx); + uint64_t amount = pd.m_amount_in; + uint64_t fee = amount - pd.m_amount_out; std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 4e014462e..5d51efc12 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -225,6 +225,24 @@ static uint64_t decodeRct(const rct::rctSig & rv, const rct::key & sk, unsigned //---------------------------------------------------------------------------------------------------- void wallet2::process_new_transaction(const cryptonote::transaction& tx, const std::vector &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool) { + class lazy_txid_getter + { + const cryptonote::transaction &tx; + crypto::hash lazy_txid; + bool computed; + public: + lazy_txid_getter(const transaction &tx): tx(tx), computed(false) {} + const crypto::hash &operator()() + { + if (!computed) + { + lazy_txid = cryptonote::get_transaction_hash(tx); + computed = true; + } + return lazy_txid; + } + } txid(tx); + if (!miner_tx) process_unconfirmed(tx, height); std::vector outs; @@ -235,7 +253,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s if(!parse_tx_extra(tx.extra, tx_extra_fields)) { // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key - LOG_PRINT_L0("Transaction extra has unsupported format: " << get_transaction_hash(tx)); + LOG_PRINT_L0("Transaction extra has unsupported format: " << txid()); } // Don't try to extract tx public key if tx has no ouputs @@ -244,7 +262,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s tx_extra_pub_key pub_key_field; if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field)) { - LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << get_transaction_hash(tx)); + LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid()); if(0 != m_callback) m_callback->on_skip_transaction(height, tx); return; @@ -452,7 +470,8 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s td.m_block_height = height; td.m_internal_output_index = o; td.m_global_output_index = o_indices[o]; - td.m_tx = tx; + td.m_tx = (const cryptonote::transaction_prefix&)tx; + td.m_txid = txid(); td.m_key_image = ki[o]; td.m_amount = tx.vout[o].amount; if (td.m_amount == 0) @@ -466,9 +485,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s } set_unspent(td); m_key_images[td.m_key_image] = m_transfers.size()-1; - LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx)); + LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid()); if (0 != m_callback) - m_callback->on_money_received(height, td.m_tx, td.m_amount); + m_callback->on_money_received(height, tx, td.m_amount); } } else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx.vout[o].amount) @@ -492,7 +511,8 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s td.m_block_height = height; td.m_internal_output_index = o; td.m_global_output_index = o_indices[o]; - td.m_tx = tx; + td.m_tx = (const cryptonote::transaction_prefix&)tx; + td.m_txid = txid(); td.m_amount = tx.vout[o].amount; if (td.m_amount == 0) { @@ -506,9 +526,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s THROW_WALLET_EXCEPTION_IF(td.m_key_image != ki[o], error::wallet_internal_error, "Inconsistent key images"); THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status"); - LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << get_transaction_hash(tx)); + LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid()); if (0 != m_callback) - m_callback->on_money_received(height, td.m_tx, td.m_amount); + m_callback->on_money_received(height, tx, td.m_amount); } } } @@ -533,11 +553,11 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s std::string(", expected ") + print_money(td.amount())); } amount = td.amount(); - LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << get_transaction_hash(tx)); + LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << txid()); tx_money_spent_in_ins += amount; set_spent(td, height); if (0 != m_callback) - m_callback->on_money_spent(height, td.m_tx, amount, tx); + m_callback->on_money_spent(height, tx, amount, tx); } } @@ -589,7 +609,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s } payment_details payment; - payment.m_tx_hash = cryptonote::get_transaction_hash(tx); + payment.m_tx_hash = txid(); payment.m_amount = received; payment.m_block_height = height; payment.m_unlock_time = tx.unlock_time; @@ -604,6 +624,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s //---------------------------------------------------------------------------------------------------- void wallet2::process_unconfirmed(const cryptonote::transaction& tx, uint64_t height) { + if (m_unconfirmed_txs.empty()) + return; + crypto::hash txid = get_transaction_hash(tx); auto unconf_it = m_unconfirmed_txs.find(txid); if(unconf_it != m_unconfirmed_txs.end()) { @@ -915,7 +938,7 @@ void wallet2::update_pool_state() std::unordered_map::iterator it = m_unconfirmed_txs.begin(); while (it != m_unconfirmed_txs.end()) { - const std::string txid = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(it->second.m_tx)); + const std::string txid = epee::string_tools::pod_to_hex(it->first); bool found = false; for (auto it2: res.transactions) { @@ -1141,7 +1164,7 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re blocks_fetched = 0; uint64_t added_blocks = 0; size_t try_count = 0; - crypto::hash last_tx_hash_id = m_transfers.size() ? get_transaction_hash(m_transfers.back().m_tx) : null_hash; + crypto::hash last_tx_hash_id = m_transfers.size() ? m_transfers.back().m_txid : null_hash; std::list short_chain_history; boost::thread pull_thread; uint64_t blocks_start_height; @@ -1213,7 +1236,7 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re } } } - if(last_tx_hash_id != (m_transfers.size() ? get_transaction_hash(m_transfers.back().m_tx) : null_hash)) + if(last_tx_hash_id != (m_transfers.size() ? m_transfers.back().m_txid : null_hash)) received_money = true; try @@ -2179,11 +2202,9 @@ float wallet2::get_output_relatedness(const transfer_details &td0, const transfe { int dh; -#if 0 // expensive test, and same tx will fall onto the same block height below - if (get_transaction_hash(td0.m_tx) == get_transaction_hash(td1.m_tx)) + if (td0.m_txid == td1.m_txid) return 1.0f; -#endif // same block height -> possibly tx burst, or same tx (since above is disabled) dh = td0.m_block_height > td1.m_block_height ? td0.m_block_height - td1.m_block_height : td1.m_block_height - td0.m_block_height; @@ -2269,7 +2290,7 @@ void wallet2::add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t amo utd.m_amount_out += d.amount; utd.m_change = change_amount; utd.m_sent_time = time(NULL); - utd.m_tx = tx; + utd.m_tx = (const cryptonote::transaction_prefix&)tx; utd.m_dests = dests; utd.m_payment_id = payment_id; utd.m_state = wallet2::unconfirmed_transfer_details::pending; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 4c361df81..488902d5d 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -99,7 +99,8 @@ namespace tools struct transfer_details { uint64_t m_block_height; - cryptonote::transaction m_tx; + cryptonote::transaction_prefix m_tx; + crypto::hash m_txid; size_t m_internal_output_index; uint64_t m_global_output_index; bool m_spent; @@ -123,7 +124,7 @@ namespace tools struct unconfirmed_transfer_details { - cryptonote::transaction m_tx; + cryptonote::transaction_prefix m_tx; uint64_t m_amount_in; uint64_t m_amount_out; uint64_t m_change; @@ -502,9 +503,9 @@ namespace tools }; } BOOST_CLASS_VERSION(tools::wallet2, 14) -BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 2) +BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 3) BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1) -BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 4) +BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 5) BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 2) namespace boost @@ -535,7 +536,17 @@ namespace boost a & x.m_block_height; a & x.m_global_output_index; a & x.m_internal_output_index; - a & x.m_tx; + if (ver < 3) + { + cryptonote::transaction tx; + a & tx; + x.m_tx = (const cryptonote::transaction_prefix&)tx; + x.m_txid = cryptonote::get_transaction_hash(tx); + } + else + { + a & x.m_tx; + } a & x.m_spent; a & x.m_key_image; if (ver < 1) @@ -552,6 +563,9 @@ namespace boost return; } a & x.m_spent_height; + if (ver < 3) + return; + a & x.m_txid; } template @@ -559,7 +573,16 @@ namespace boost { a & x.m_change; a & x.m_sent_time; - a & x.m_tx; + if (ver < 5) + { + cryptonote::transaction tx; + a & tx; + x.m_tx = (const cryptonote::transaction_prefix&)tx; + } + else + { + a & x.m_tx; + } if (ver < 1) return; a & x.m_dests; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 20a9ebe93..1786b776f 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -729,7 +729,7 @@ namespace tools rpc_transfers.amount = td.amount(); rpc_transfers.spent = td.m_spent; rpc_transfers.global_index = td.m_global_output_index; - rpc_transfers.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(td.m_tx)); + rpc_transfers.tx_hash = epee::string_tools::pod_to_hex(td.m_txid); rpc_transfers.tx_size = txBlob.size(); res.transfers.push_back(rpc_transfers); } diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp index 6bf910101..585328348 100644 --- a/tests/functional_tests/transactions_flow_test.cpp +++ b/tests/functional_tests/transactions_flow_test.cpp @@ -281,7 +281,7 @@ bool transactions_flow_test(std::string& working_folder, w2.get_transfers(tc); BOOST_FOREACH(tools::wallet2::transfer_details& td, tc) { - auto it = txs.find(get_transaction_hash(td.m_tx)); + auto it = txs.find(td.m_txid); CHECK_AND_ASSERT_MES(it != txs.end(), false, "transaction not found in local cache"); it->second.m_received_count += 1; } diff --git a/tests/unit_tests/output_selection.cpp b/tests/unit_tests/output_selection.cpp index a3164fa4e..4344d1ffc 100644 --- a/tests/unit_tests/output_selection.cpp +++ b/tests/unit_tests/output_selection.cpp @@ -42,6 +42,11 @@ static tools::wallet2::transfer_container make_transfers_container(size_t N) tools::wallet2::transfer_details &td = transfers.back(); td.m_block_height = 1000; td.m_spent = false; + td.m_txid = cryptonote::null_hash; + td.m_txid.data[0] = n & 0xff; + td.m_txid.data[1] = (n >> 8) & 0xff; + td.m_txid.data[2] = (n >> 16) & 0xff; + td.m_txid.data[3] = (n >> 24) & 0xff; } return transfers; } -- cgit v1.2.3 From d4b62a1e295a7fb19de6081733b1d8e0610cbf08 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 10 Aug 2016 12:48:20 +0100 Subject: rct amount key modified as per luigi1111's recommendations This allows the key to be not the same for two outputs sent to the same address (eg, if you pay yourself, and also get change back). Also remove the key amounts lists and return parameters since we don't actually generate random ones, so we don't need to save them as we can recalculate them when needed if we have the correct keys. --- src/crypto/crypto.cpp | 2 +- src/crypto/crypto.h | 5 ++++ src/cryptonote_core/cryptonote_format_utils.cpp | 13 ++++++--- src/cryptonote_core/cryptonote_format_utils.h | 2 +- src/ringct/rctOps.cpp | 18 +++--------- src/ringct/rctOps.h | 6 ++-- src/ringct/rctSigs.cpp | 28 ++++-------------- src/ringct/rctSigs.h | 2 -- src/simplewallet/simplewallet.cpp | 28 +++++++++++++----- src/wallet/wallet2.cpp | 39 ++++++++++++------------- src/wallet/wallet2.h | 5 +--- src/wallet/wallet_rpc_server.cpp | 31 -------------------- src/wallet/wallet_rpc_server_commands_defs.h | 6 ---- tests/core_tests/rct.cpp | 17 ++++++----- tests/unit_tests/ringct.cpp | 16 +++++----- 15 files changed, 85 insertions(+), 133 deletions(-) (limited to 'src/simplewallet') diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index f0ee3bdc3..250779ac3 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -151,7 +151,7 @@ namespace crypto { return true; } - static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { + void crypto_ops::derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { struct { key_derivation derivation; char output_index[(sizeof(size_t) * 8 + 6) / 7]; diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index aa437d57d..b396fc7db 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -113,6 +113,8 @@ namespace crypto { friend bool secret_key_to_public_key(const secret_key &, public_key &); static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); + static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res); + friend void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res); static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); @@ -181,6 +183,9 @@ namespace crypto { const public_key &base, public_key &derived_key) { return crypto_ops::derive_public_key(derivation, output_index, base, derived_key); } + inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { + return crypto_ops::derivation_to_scalar(derivation, output_index, res); + } inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key) { crypto_ops::derive_secret_key(derivation, output_index, base, derived_key); diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 8f4020829..6a3172d4e 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -458,8 +458,9 @@ namespace cryptonote return encrypt_payment_id(payment_id, public_key, secret_key); } //--------------------------------------------------------------- - bool construct_tx_and_get_tx_keys(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &amount_keys, bool rct) + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct) { + std::vector amount_keys; tx.vin.clear(); tx.vout.clear(); tx.signatures.clear(); @@ -577,6 +578,12 @@ namespace cryptonote bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << txkey.sec << ")"); + if (tx.version > 1) + { + crypto::secret_key scalar1; + crypto::derivation_to_scalar(derivation, output_index, scalar1); + amount_keys.push_back(scalar1); + } r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key); CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")"); @@ -686,7 +693,6 @@ namespace cryptonote destinations.push_back(rct::pk2rct(boost::get(tx.vout[i].target).key)); outamounts.push_back(tx.vout[i].amount); amount_out += tx.vout[i].amount; - amount_keys.push_back(rct::rct2sk(rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(shuffled_dsts[i].addr.m_view_public_key), rct::sk2rct(txkey.sec))))); } if (use_simple_rct) @@ -745,8 +751,7 @@ namespace cryptonote bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time) { crypto::secret_key tx_key; - std::vector amount_keys; - return construct_tx_and_get_tx_keys(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key, amount_keys); + return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key); } //--------------------------------------------------------------- bool get_inputs_money_amount(const transaction& tx, uint64_t& money) diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h index f70b22573..5da256921 100644 --- a/src/cryptonote_core/cryptonote_format_utils.h +++ b/src/cryptonote_core/cryptonote_format_utils.h @@ -74,7 +74,7 @@ namespace cryptonote //--------------------------------------------------------------- bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time); - bool construct_tx_and_get_tx_keys(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &amount_keys, bool rct = false); + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct = false); template bool find_tx_extra_field_by_type(const std::vector& tx_extra_fields, T& field) diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index b8a0d26ad..d54aa667f 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -741,28 +741,18 @@ void fe_mul(fe h,const fe f,const fe g) //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a // where C= aG + bH - void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1) { + void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec) { + key sharedSec1 = hash_to_scalar(sharedSec); key sharedSec2 = hash_to_scalar(sharedSec1); //encode sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes); sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes); } - void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk) { - key esk; - //compute shared secret - skpkGen(esk, unmasked.senderPk); - key sharedSec1 = hash_to_scalar(scalarmultKey(receiverPk, esk)); - ecdhEncodeFromSharedSecret(unmasked, sharedSec1); - } - void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1) { + void ecdhDecode(ecdhTuple & masked, const key & sharedSec) { + key sharedSec1 = hash_to_scalar(sharedSec); key sharedSec2 = hash_to_scalar(sharedSec1); //decode sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes); sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes); } - void ecdhDecode(ecdhTuple & masked, const key & receiverSk) { - //compute shared secret - key sharedSec1 = hash_to_scalar(scalarmultKey(masked.senderPk, receiverSk)); - ecdhDecodeFromSharedSecret(masked, sharedSec1); - } } diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h index 225c5abb9..1e71c645d 100644 --- a/src/ringct/rctOps.h +++ b/src/ringct/rctOps.h @@ -165,9 +165,7 @@ namespace rct { //Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a // where C= aG + bH - void ecdhEncodeFromSharedSecret(ecdhTuple & unmasked, const key & sharedSec1); - void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk); - void ecdhDecodeFromSharedSecret(ecdhTuple & masked, const key & sharedSec1); - void ecdhDecode(ecdhTuple & masked, const key & receiverSk); + void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec); + void ecdhDecode(ecdhTuple & masked, const key & sharedSec); } #endif /* RCTOPS_H */ diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index d42be0fcc..73c124067 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -613,7 +613,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(amounts[i]); - ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]); + ecdhEncode(rv.ecdhInfo[i], amount_keys[i]); } @@ -679,7 +679,7 @@ namespace rct { //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); rv.ecdhInfo[i].amount = d2h(outamounts[i]); - ecdhEncodeFromSharedSecret(rv.ecdhInfo[i], amount_keys[i]); + ecdhEncode(rv.ecdhInfo[i], amount_keys[i]); } //set txn fee @@ -821,7 +821,7 @@ namespace rct { //decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1) // uses the attached ecdh info to find the amounts represented by each output commitment // must know the destination private key to find the correct amount, else will return a random number - static xmr_amount decodeRctMain(const rctSig & rv, const key & sk, unsigned int i, key & mask, void (*decode)(ecdhTuple&, const key&)) { + xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) { CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig"); CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs"); @@ -829,7 +829,7 @@ namespace rct { //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - (*decode)(ecdh_info, sk); + ecdhDecode(ecdh_info, sk); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; @@ -845,20 +845,12 @@ namespace rct { return h2d(amount); } - xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) { - return decodeRctMain(rv, sk, i, mask, &ecdhDecode); - } - - xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask) { - return decodeRctMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret); - } - xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i) { key mask; return decodeRct(rv, sk, i, mask); } - static xmr_amount decodeRctSimpleMain(const rctSig & rv, const key & sk, unsigned int i, key &mask, void (*decode)(ecdhTuple &ecdh, const key&)) { + xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) { CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig"); CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs"); CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs"); @@ -866,7 +858,7 @@ namespace rct { //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; - (*decode)(ecdh_info, sk); + ecdhDecode(ecdh_info, sk); mask = ecdh_info.mask; key amount = ecdh_info.amount; key C = rv.outPk[i].mask; @@ -882,14 +874,6 @@ namespace rct { return h2d(amount); } - xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) { - return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecode); - } - - xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key &mask) { - return decodeRctSimpleMain(rv, sk, i, mask, &ecdhDecodeFromSharedSecret); - } - xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i) { key mask; return decodeRctSimple(rv, sk, i, mask); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index bf9d4be81..8a686bd64 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -142,9 +142,7 @@ namespace rct { bool verRct(const rctSig & rv); bool verRctSimple(const rctSig & rv); xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask); - xmr_amount decodeRctFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask); xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i); - xmr_amount decodeRctSimpleFromSharedSecret(const rctSig & rv, const key & sk, unsigned int i, key & mask); xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask); xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i); } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 9e7341451..7c5e8e541 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3077,15 +3077,27 @@ bool simple_wallet::check_tx_key(const std::vector &args_) try { rct::key Ctmp; - rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key))); - rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n]; - rct::ecdhDecodeFromSharedSecret(ecdh_info, amount_key); - rct::key C = tx.rct_signatures.outPk[n].mask; - rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H); - if (rct::equalKeys(C, Ctmp)) - amount = rct::h2d(ecdh_info.amount); - else + //rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key))); + crypto::key_derivation derivation; + bool r = crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation); + if (!r) + { + LOG_ERROR("Failed to generate key derivation to decode rct output " << n); amount = 0; + } + else + { + crypto::secret_key scalar1; + crypto::derivation_to_scalar(derivation, n, scalar1); + rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n]; + rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1)); + rct::key C = tx.rct_signatures.outPk[n].mask; + rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H); + if (rct::equalKeys(C, Ctmp)) + amount = rct::h2d(ecdh_info.amount); + else + amount = 0; + } } catch (...) { amount = 0; } } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c3fb160a0..b3b8e6561 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -207,16 +207,25 @@ void wallet2::check_acc_out(const account_keys &acc, const tx_out &o, const cryp error = false; } //---------------------------------------------------------------------------------------------------- -static uint64_t decodeRct(const rct::rctSig & rv, const rct::key & sk, unsigned int i, rct::key & mask) +static uint64_t decodeRct(const rct::rctSig & rv, const crypto::public_key pub, const crypto::secret_key &sec, unsigned int i, rct::key & mask) { + crypto::key_derivation derivation; + bool r = crypto::generate_key_derivation(pub, sec, derivation); + if (!r) + { + LOG_ERROR("Failed to generate key derivation to decode rct output " << i); + return 0; + } + crypto::secret_key scalar1; + crypto::derivation_to_scalar(derivation, i, scalar1); try { switch (rv.type) { case rct::RCTTypeSimple: - return rct::decodeRctSimpleFromSharedSecret(rv, sk, i, mask); + return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask); case rct::RCTTypeFull: - return rct::decodeRctFromSharedSecret(rv, sk, i, mask); + return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask); default: LOG_ERROR("Unsupported rct type: " << rv.type); return 0; @@ -308,8 +317,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s if (money_transfered == 0) { const cryptonote::account_keys& keys = m_account.get_keys(); - rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); - money_transfered = tools::decodeRct(tx.rct_signatures, amount_key, 0, mask[0]); + money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, 0, mask[0]); } amount[0] = money_transfered; tx_money_got_in_outs = money_transfered; @@ -352,8 +360,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s if (money_transfered[i] == 0) { const cryptonote::account_keys& keys = m_account.get_keys(); - rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); - money_transfered[i] = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]); + money_transfered[i] = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]); } tx_money_got_in_outs += money_transfered[i]; amount[i] = money_transfered[i]; @@ -401,8 +408,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s if (money_transfered[i] == 0) { const cryptonote::account_keys& keys = m_account.get_keys(); - rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); - money_transfered[i] = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]); + money_transfered[i] = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]); } tx_money_got_in_outs += money_transfered[i]; amount[i] = money_transfered[i]; @@ -434,8 +440,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s if (money_transfered == 0) { const cryptonote::account_keys& keys = m_account.get_keys(); - rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(pub_key_field.pub_key), rct::sk2rct(keys.m_view_secret_key))); - money_transfered = tools::decodeRct(tx.rct_signatures, amount_key, i, mask[i]); + money_transfered = tools::decodeRct(tx.rct_signatures, pub_key_field.pub_key, keys.m_view_secret_key, i, mask[i]); } amount[i] = money_transfered; tx_money_got_in_outs += money_transfered; @@ -2896,8 +2901,7 @@ void wallet2::transfer_selected(const std::vector amount_keys; - bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys); + bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -2924,7 +2928,6 @@ void wallet2::transfer_selected(const std::vector amount_keys; - bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, dsts, extra, tx, unlock_time, tx_key, amount_keys, true); + bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, dsts, extra, tx, unlock_time, tx_key, true); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -3135,7 +3137,6 @@ void wallet2::transfer_selected_rct(std::vector &outs, size_t num_outputs, } crypto::secret_key tx_key; - std::vector amount_keys; - bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys); + bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -3785,7 +3785,6 @@ void wallet2::transfer_from(const std::vector &outs, size_t num_outputs, ptx.change_dts = change_dts; ptx.selected_transfers = selected_transfers; ptx.tx_key = tx_key; - ptx.amount_keys = amount_keys; ptx.dests = dsts; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 488902d5d..0d61f90e2 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -162,7 +162,6 @@ namespace tools std::list selected_transfers; std::string key_images; crypto::secret_key tx_key; - std::vector amount_keys; std::vector dests; }; @@ -828,8 +827,7 @@ namespace tools } crypto::secret_key tx_key; - std::vector amount_keys; - bool r = cryptonote::construct_tx_and_get_tx_keys(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key, amount_keys); + bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); @@ -855,7 +853,6 @@ namespace tools ptx.change_dts = change_dts; ptx.selected_transfers = selected_transfers; ptx.tx_key = tx_key; - ptx.amount_keys = amount_keys; ptx.dests = dsts; } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 1786b776f..4c190b005 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -256,13 +256,6 @@ namespace tools if (req.get_tx_key) { res.tx_key = epee::string_tools::pod_to_hex(ptx_vector.back().tx_key); - if (ptx_vector.back().tx.version > 1) - { - for (const auto &i: ptx_vector.back().amount_keys) - { - res.amount_keys.push_back(epee::string_tools::pod_to_hex(i)); - } - } } return true; } @@ -325,14 +318,6 @@ namespace tools if (req.get_tx_keys) { res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key)); - res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::key_list()); - if (ptx.tx.version > 1) - { - for (const auto &i: ptx.amount_keys) - { - res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i)); - } - } } } @@ -381,14 +366,6 @@ namespace tools if (req.get_tx_keys) { res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key)); - res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_SWEEP_DUST::key_list()); - if (ptx.tx.version > 1) - { - for (const auto &i: ptx.amount_keys) - { - res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i)); - } - } } } @@ -450,14 +427,6 @@ namespace tools if (req.get_tx_keys) { res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key)); - res.amount_key_list.push_back(wallet_rpc::COMMAND_RPC_SWEEP_ALL::key_list()); - if (ptx.tx.version > 1) - { - for (const auto &i: ptx.amount_keys) - { - res.amount_key_list.back().keys.push_back(epee::string_tools::pod_to_hex(i)); - } - } } } diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 4df259242..27b897dab 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -178,12 +178,10 @@ namespace wallet_rpc { std::list tx_hash_list; std::list tx_key_list; - std::list amount_key_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) KV_SERIALIZE(tx_key_list) - KV_SERIALIZE(amount_key_list) END_KV_SERIALIZE_MAP() }; }; @@ -214,12 +212,10 @@ namespace wallet_rpc { std::list tx_hash_list; std::list tx_key_list; - std::list amount_key_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) KV_SERIALIZE(tx_key_list) - KV_SERIALIZE(amount_key_list) END_KV_SERIALIZE_MAP() }; }; @@ -260,12 +256,10 @@ namespace wallet_rpc { std::list tx_hash_list; std::list tx_key_list; - std::list amount_key_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash_list) KV_SERIALIZE(tx_key_list) - KV_SERIALIZE(amount_key_list) END_KV_SERIALIZE_MAP() }; }; diff --git a/tests/core_tests/rct.cpp b/tests/core_tests/rct.cpp index d03e208b6..b358ce8b2 100644 --- a/tests/core_tests/rct.cpp +++ b/tests/core_tests/rct.cpp @@ -116,20 +116,22 @@ bool gen_rct_tx_validation_base::generate_with(std::vector& ev destinations.push_back(td); // 30 -> 7.39 * 4 crypto::secret_key tx_key; - std::vector amount_keys; - bool r = construct_tx_and_get_tx_keys(miner_accounts[n].get_keys(), sources, destinations, std::vector(), rct_txes[n], 0, tx_key, amount_keys, true); + bool r = construct_tx_and_get_tx_key(miner_accounts[n].get_keys(), sources, destinations, std::vector(), rct_txes[n], 0, tx_key, true); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); events.push_back(rct_txes[n]); starting_rct_tx_hashes.push_back(get_transaction_hash(rct_txes[n])); - crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(rct_txes[n]); for (size_t o = 0; o < 4; ++o) { - rct::key amount_key = rct::hash_to_scalar(rct::scalarmultKey(rct::pk2rct(tx_pub_key), rct::sk2rct(miner_accounts[n].get_keys().m_view_secret_key))); + crypto::key_derivation derivation; + bool r = crypto::generate_key_derivation(destinations[o].addr.m_view_public_key, tx_key, derivation); + CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); + crypto::secret_key amount_key; + crypto::derivation_to_scalar(derivation, o, amount_key); if (rct_txes[n].rct_signatures.type == rct::RCTTypeSimple) - rct::decodeRctSimpleFromSharedSecret(rct_txes[n].rct_signatures, amount_key, o, rct_tx_masks[o+n*4]); + rct::decodeRctSimple(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4]); else - rct::decodeRctFromSharedSecret(rct_txes[n].rct_signatures, amount_key, o, rct_tx_masks[o+n*4]); + rct::decodeRct(rct_txes[n].rct_signatures, rct::sk2rct(amount_key), o, rct_tx_masks[o+n*4]); } CHECK_AND_ASSERT_MES(generator.construct_block_manually(blk_txes[n], blk_last, miner_account, @@ -205,8 +207,7 @@ bool gen_rct_tx_validation_base::generate_with(std::vector& ev transaction tx; crypto::secret_key tx_key; - std::vector amount_keys; - bool r = construct_tx_and_get_tx_keys(miner_accounts[0].get_keys(), sources, destinations, std::vector(), tx, 0, tx_key, amount_keys, true); + bool r = construct_tx_and_get_tx_key(miner_accounts[0].get_keys(), sources, destinations, std::vector(), tx, 0, tx_key, true); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); if (post_tx) diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 16234ce52..224e32e61 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -196,7 +196,7 @@ TEST(ringct, range_proofs) ASSERT_TRUE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); + ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask)); // Ring CT with failing MG sig part should not verify! // Since sum of inputs != outputs @@ -213,7 +213,7 @@ TEST(ringct, range_proofs) ASSERT_FALSE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); + ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask)); } TEST(ringct, range_proofs_with_fee) @@ -261,7 +261,7 @@ TEST(ringct, range_proofs_with_fee) ASSERT_TRUE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); + ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask)); // Ring CT with failing MG sig part should not verify! // Since sum of inputs != outputs @@ -278,7 +278,7 @@ TEST(ringct, range_proofs_with_fee) ASSERT_FALSE(verRct(s)); //decode received amount - ASSERT_TRUE(decodeRctFromSharedSecret(s, amount_keys[1], 1, mask)); + ASSERT_TRUE(decodeRct(s, amount_keys[1], 1, mask)); } TEST(ringct, simple) @@ -336,7 +336,7 @@ TEST(ringct, simple) ASSERT_TRUE(verRctSimple(s)); //decode received amount corresponding to output pubkey index 1 - ASSERT_TRUE(decodeRctSimpleFromSharedSecret(s, amount_keys[1], 1, mask)); + ASSERT_TRUE(decodeRctSimple(s, amount_keys[1], 1, mask)); } static rct::rctSig make_sample_rct_sig(int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[], bool last_is_fee) @@ -843,17 +843,17 @@ static const xmr_amount test_amounts[]={0, 1, 2, 3, 4, 5, 10000, 100000000000000 TEST(ringct, ecdh_roundtrip) { - key k, P1; + key k; ecdhTuple t0, t1; for (auto amount: test_amounts) { - skpkGen(k, P1); + skGen(k); t0.mask = skGen(); t0.amount = d2h(amount); t1 = t0; - ecdhEncode(t1, P1); + ecdhEncode(t1, k); ecdhDecode(t1, k); ASSERT_TRUE(t0.mask == t1.mask); ASSERT_TRUE(equalKeys(t0.mask, t1.mask)); -- cgit v1.2.3 From fbd7c359ee10ca08fe3c7c95464fc054ea42a9b8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Aug 2016 13:45:33 +0100 Subject: wallet: fix some "may be used uninitialized" warnings The compiler can't always work out the _found booleans are set iff the value is initialized. --- src/common/json_util.h | 4 ++-- src/simplewallet/simplewallet.cpp | 16 ++++++++-------- src/wallet/wallet2.cpp | 31 +++++++++++++++---------------- 3 files changed, 25 insertions(+), 26 deletions(-) (limited to 'src/simplewallet') diff --git a/src/common/json_util.h b/src/common/json_util.h index 6f8b4c18f..45046a4fb 100644 --- a/src/common/json_util.h +++ b/src/common/json_util.h @@ -28,8 +28,8 @@ #pragma once -#define GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, name, type, jtype, mandatory) \ - type field_##name; \ +#define GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, name, type, jtype, mandatory, def) \ + type field_##name = def; \ bool field_##name##_found = false; \ (void)field_##name##_found; \ do if (json.HasMember(#name)) \ diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 7c5e8e541..44b5b0c70 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -979,22 +979,22 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m return false; } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, version, unsigned, Uint, true); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, version, unsigned, Uint, true, 0); const int current_version = 1; if (field_version > current_version) { fail_msg_writer() << boost::format(tr("Version %u too new, we can only grok up to %u")) % field_version % current_version; return false; } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, filename, std::string, String, true); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, filename, std::string, String, true, std::string()); - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, scan_from_height, uint64_t, Uint64, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, scan_from_height, uint64_t, Uint64, false, 0); bool recover = field_scan_from_height_found; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, password, std::string, String, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, password, std::string, String, false, std::string()); password = field_password; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, viewkey, std::string, String, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, viewkey, std::string, String, false, std::string()); crypto::secret_key viewkey; if (field_viewkey_found) { @@ -1012,7 +1012,7 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m } } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, spendkey, std::string, String, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, spendkey, std::string, String, false, std::string()); crypto::secret_key spendkey; if (field_spendkey_found) { @@ -1030,7 +1030,7 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m } } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed, std::string, String, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed, std::string, String, false, std::string()); std::string old_language; if (field_seed_found) { @@ -1043,7 +1043,7 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m m_restore_deterministic_wallet = true; } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, address, std::string, String, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, address, std::string, String, false, std::string()); // compatibility checks if (!field_seed_found && !field_viewkey_found) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 0a2a5ec9d..99866dbeb 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1495,26 +1495,25 @@ bool wallet2::load_keys(const std::string& keys_file_name, const std::string& pa const char *field_key_data = json["key_data"].GetString(); account_data = std::string(field_key_data, field_key_data + json["key_data"].GetStringLength()); - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed_language, std::string, String, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed_language, std::string, String, false, std::string()); if (field_seed_language_found) { set_seed_language(field_seed_language); } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, watch_only, int, Int, false); - m_watch_only = field_watch_only_found && field_watch_only; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, always_confirm_transfers, int, Int, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, watch_only, int, Int, false, false); + m_watch_only = field_watch_only; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, always_confirm_transfers, int, Int, false, false); m_always_confirm_transfers = field_always_confirm_transfers_found && field_always_confirm_transfers; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, store_tx_keys, int, Int, false); - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, store_tx_info, int, Int, false); - m_store_tx_info = (field_store_tx_keys_found && (field_store_tx_keys != 0)) - || (field_store_tx_info_found && (field_store_tx_info != 0)); - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, default_mixin, unsigned int, Uint, false); - m_default_mixin = field_default_mixin_found ? field_default_mixin : 0; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, default_fee_multiplier, unsigned int, Uint, false); - m_default_fee_multiplier = field_default_fee_multiplier_found ? field_default_fee_multiplier : 0; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, auto_refresh, int, Int, false); - m_auto_refresh = !field_auto_refresh_found || (field_auto_refresh != 0); - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, refresh_type, int, Int, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, store_tx_keys, int, Int, false, true); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, store_tx_info, int, Int, false, true); + m_store_tx_info = ((field_store_tx_keys != 0) || (field_store_tx_info != 0)); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, default_mixin, unsigned int, Uint, false, 0); + m_default_mixin = field_default_mixin; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, default_fee_multiplier, unsigned int, Uint, false, 0); + m_default_fee_multiplier = field_default_fee_multiplier; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, auto_refresh, int, Int, false, true); + m_auto_refresh = field_auto_refresh; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, refresh_type, int, Int, false, RefreshType::RefreshDefault); m_refresh_type = RefreshType::RefreshDefault; if (field_refresh_type_found) { @@ -1523,7 +1522,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const std::string& pa else LOG_PRINT_L0("Unknown refresh-type value (" << field_refresh_type << "), using default"); } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, refresh_height, uint64_t, Uint64, false); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, refresh_height, uint64_t, Uint64, false, 0); if (field_refresh_height_found) m_refresh_from_block_height = field_refresh_height; } -- cgit v1.2.3