diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 6578776b..5f8e4024 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 f4fd8bd3..6dac8e88 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 687373fe..c4a29719 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 94b67f2d..57f852d6 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 c8c440a0..c8fae6ed 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 a6c9faa8..ef77f68c 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 ca9d9fb7..c45b6482 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 9bcc2607..7d00dde0 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 d7f01d9e..ea92a028 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 ef5f72fb..a07c7204 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)