aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.cpp1
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.h4
-rw-r--r--src/simplewallet/simplewallet.cpp85
-rw-r--r--src/simplewallet/simplewallet.h2
-rw-r--r--src/wallet/CMakeLists.txt60
-rw-r--r--src/wallet/wallet2.cpp53
-rw-r--r--src/wallet/wallet2.h39
7 files changed, 186 insertions, 58 deletions
diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp
index 234422e3d..d88f66e3b 100644
--- a/src/cryptonote_core/cryptonote_format_utils.cpp
+++ b/src/cryptonote_core/cryptonote_format_utils.cpp
@@ -480,6 +480,7 @@ namespace cryptonote
tx.extra = extra;
keypair txkey = keypair::generate();
+ remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));
add_tx_pub_key_to_extra(tx, txkey.pub);
tx_key = txkey.sec;
diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h
index d5dd6494d..9f9ed8625 100644
--- a/src/cryptonote_core/cryptonote_format_utils.h
+++ b/src/cryptonote_core/cryptonote_format_utils.h
@@ -93,9 +93,9 @@ namespace cryptonote
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct = false);
template<typename T>
- bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field)
+ bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field, size_t index = 0)
{
- auto it = std::find_if(tx_extra_fields.begin(), tx_extra_fields.end(), [](const tx_extra_field& f) { return typeid(T) == f.type(); });
+ auto it = std::find_if(tx_extra_fields.begin(), tx_extra_fields.end(), [&index](const tx_extra_field& f) { return typeid(T) == f.type() && !index--; });
if(tx_extra_fields.end() == it)
return false;
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index a2b9405c8..515fc5b22 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -280,7 +280,8 @@ std::string simple_wallet::get_commands_str()
bool simple_wallet::viewkey(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
// don't log
- std::cout << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << std::endl;
+ std::cout << "secret: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << std::endl;
+ std::cout << "public: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_view_public_key) << std::endl;
return true;
}
@@ -288,7 +289,8 @@ bool simple_wallet::viewkey(const std::vector<std::string> &args/* = std::vector
bool simple_wallet::spendkey(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
// don't log
- std::cout << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key) << std::endl;
+ std::cout << "secret: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key) << std::endl;
+ std::cout << "public: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_spend_public_key) << std::endl;
return true;
}
@@ -1134,7 +1136,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
else if (!m_generate_from_json.empty())
{
m_wallet_file = m_generate_from_json;
- if (!tools::wallet2::make_from_json(vm, m_wallet_file))
+ m_wallet = tools::wallet2::make_from_json(vm, m_wallet_file);
+ if (!m_wallet)
return false;
}
else
@@ -1737,18 +1740,23 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
bool filter = false;
bool available = false;
- if (!args.empty())
+ bool verbose = false;
+ for (const auto &arg: args)
{
- if (args[0] == "available")
+ if (arg == "available")
{
filter = true;
available = true;
}
- else if (args[0] == "unavailable")
+ else if (arg == "unavailable")
{
filter = true;
available = false;
}
+ else if (arg == "verbose")
+ {
+ verbose = true;
+ }
}
tools::wallet2::transfer_container transfers;
@@ -1761,17 +1769,24 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
{
if (!transfers_found)
{
- message_writer() << boost::format("%21s%8s%12s%8s%16s%68s") % tr("amount") % tr("spent") % tr("unlocked") % tr("ringct") % tr("global index") % tr("tx id");
+ std::string verbose_string;
+ if (verbose)
+ verbose_string = (boost::format("%68s%68s") % tr("pubkey") % tr("key image")).str();
+ message_writer() << boost::format("%21s%8s%12s%8s%16s%68s%s") % tr("amount") % tr("spent") % tr("unlocked") % tr("ringct") % tr("global index") % tr("tx id") % verbose_string;
transfers_found = true;
}
+ std::string verbose_string;
+ if (verbose)
+ verbose_string = (boost::format("%68s%68s") % td.get_public_key() % (td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : std::string('?', 64))).str();
message_writer(td.m_spent ? epee::log_space::console_color_magenta : epee::log_space::console_color_green, false) <<
- boost::format("%21s%8s%12s%8s%16u%68s") %
+ boost::format("%21s%8s%12s%8s%16u%68s%s") %
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 %
- td.m_txid;
+ td.m_txid %
+ verbose_string;
}
}
@@ -2162,12 +2177,16 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
// if more than one tx necessary, prompt user to confirm
if (m_wallet->always_confirm_transfers() || ptx_vector.size() > 1)
{
+ uint64_t total_sent = 0;
uint64_t total_fee = 0;
uint64_t dust_not_in_fee = 0;
uint64_t dust_in_fee = 0;
for (size_t n = 0; n < ptx_vector.size(); ++n)
{
total_fee += ptx_vector[n].fee;
+ for (auto i: ptx_vector[n].selected_transfers)
+ total_sent += m_wallet->get_transfer_details(i).amount();
+ total_sent -= ptx_vector[n].change_dts.amount + ptx_vector[n].fee;
if (ptx_vector[n].dust_added_to_fee)
dust_in_fee += ptx_vector[n].dust;
@@ -2176,6 +2195,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
std::stringstream prompt;
+ prompt << boost::format(tr("Sending %s. ")) % print_money(total_sent);
if (ptx_vector.size() > 1)
{
prompt << boost::format(tr("Your transaction needs to be split into %llu transactions. "
@@ -2759,7 +2779,7 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_)
return true;
}
//----------------------------------------------------------------------------------------------------
-bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx)
+bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx, const std::string &extra_message)
{
// gather info to ask the user
uint64_t amount = 0, amount_to_dests = 0, change = 0;
@@ -2800,7 +2820,12 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
fail_msg_writer() << tr("Claimed change is larger than payment to the change address");
return false;
}
- change = cd.change_dts.amount;
+ if (memcmp(&cd.change_dts.addr, &get_tx(0).change_dts.addr, sizeof(cd.change_dts.addr)))
+ {
+ fail_msg_writer() << tr("Change does to more than one address");
+ return false;
+ }
+ change += cd.change_dts.amount;
it->second -= cd.change_dts.amount;
if (it->second == 0)
dests.erase(get_account_address_as_str(m_wallet->testnet(), cd.change_dts.addr));
@@ -2817,20 +2842,35 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
if (dest_string.empty())
dest_string = tr("with no destinations");
+ std::string change_string;
+ if (change > 0)
+ {
+ std::string address = get_account_address_as_str(m_wallet->testnet(), get_tx(0).change_dts.addr);
+ change_string += (boost::format(tr("%s change to %s")) % print_money(change) % address).str();
+ }
+ else
+ change_string += tr("no change");
+
uint64_t fee = amount - amount_to_dests;
- std::string prompt_str = (boost::format(tr("Loaded %lu transactions, for %s, fee %s, change %s, %s, with min mixin %lu. Is this okay? (Y/Yes/N/No)")) % (unsigned long)get_num_txes() % print_money(amount) % print_money(fee) % print_money(change) % dest_string % (unsigned long)min_mixin).str();
+ std::string prompt_str = (boost::format(tr("Loaded %lu transactions, for %s, fee %s, %s, %s, with min mixin %lu. %sIs this okay? (Y/Yes/N/No)")) % (unsigned long)get_num_txes() % print_money(amount) % print_money(fee) % dest_string % change_string % (unsigned long)min_mixin % extra_message).str();
std::string accepted = command_line::input_line(prompt_str);
return is_it_true(accepted);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs)
{
- return accept_loaded_tx([&txs](){return txs.txes.size();}, [&txs](size_t n)->const tools::wallet2::tx_construction_data&{return txs.txes[n];});
+ std::string extra_message;
+ if (!txs.transfers.empty())
+ extra_message = (boost::format("%u outputs to import. ") % (unsigned)txs.transfers.size()).str();
+ return accept_loaded_tx([&txs](){return txs.txes.size();}, [&txs](size_t n)->const tools::wallet2::tx_construction_data&{return txs.txes[n];}, extra_message);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::accept_loaded_tx(const tools::wallet2::signed_tx_set &txs)
{
- return accept_loaded_tx([&txs](){return txs.ptx.size();}, [&txs](size_t n)->const tools::wallet2::tx_construction_data&{return txs.ptx[n].construction_data;});
+ std::string extra_message;
+ if (!txs.key_images.empty())
+ extra_message = (boost::format("%u key images to import. ") % (unsigned)txs.key_images.size()).str();
+ return accept_loaded_tx([&txs](){return txs.ptx.size();}, [&txs](size_t n)->const tools::wallet2::tx_construction_data&{return txs.ptx[n].construction_data;}, extra_message);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
@@ -2841,9 +2881,10 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
return true;
}
+ std::vector<tools::wallet2::pending_tx> ptx;
try
{
- bool r = m_wallet->sign_tx("unsigned_monero_tx", "signed_monero_tx", [&](const tools::wallet2::unsigned_tx_set &tx){ return accept_loaded_tx(tx); });
+ bool r = m_wallet->sign_tx("unsigned_monero_tx", "signed_monero_tx", ptx, [&](const tools::wallet2::unsigned_tx_set &tx){ return accept_loaded_tx(tx); });
if (!r)
{
fail_msg_writer() << tr("Failed to sign transaction");
@@ -2856,7 +2897,14 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
return true;
}
- success_msg_writer(true) << tr("Transaction successfully signed to file: ") << "signed_monero_tx";
+ std::string txids_as_text;
+ for (const auto &t: ptx)
+ {
+ if (!txids_as_text.empty())
+ txids_as_text += (", ");
+ txids_as_text += epee::string_tools::pod_to_hex(get_transaction_hash(t.tx));
+ }
+ success_msg_writer(true) << tr("Transaction successfully signed to file ") << "signed_monero_tx" << ", txid " << txids_as_text;
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -2878,12 +2926,16 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
// if more than one tx necessary, prompt user to confirm
if (m_wallet->always_confirm_transfers())
{
+ uint64_t total_sent = 0;
uint64_t total_fee = 0;
uint64_t dust_not_in_fee = 0;
uint64_t dust_in_fee = 0;
for (size_t n = 0; n < ptx_vector.size(); ++n)
{
total_fee += ptx_vector[n].fee;
+ for (auto i: ptx_vector[n].selected_transfers)
+ total_sent += m_wallet->get_transfer_details(i).amount();
+ total_sent -= ptx_vector[n].change_dts.amount + ptx_vector[n].fee;
if (ptx_vector[n].dust_added_to_fee)
dust_in_fee += ptx_vector[n].dust;
@@ -2892,6 +2944,7 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
}
std::stringstream prompt;
+ prompt << boost::format(tr("Sending %s. ")) % print_money(total_sent);
if (ptx_vector.size() > 1)
{
prompt << boost::format(tr("Your transaction needs to be split into %llu transactions. "
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index 4fe1b0417..0d83f429b 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -155,7 +155,7 @@ namespace cryptonote
uint64_t get_daemon_blockchain_height(std::string& err);
bool try_connect_to_daemon(bool silent = false);
bool ask_wallet_create_if_needed();
- bool accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx);
+ bool accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx, const std::string &extra_message = std::string());
bool accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs);
bool accept_loaded_tx(const tools::wallet2::signed_tx_set &txs);
bool get_address_from_str(const std::string &str, cryptonote::account_public_address &address, bool &has_payment_id, crypto::hash8 &payment_id);
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
index 6e087db67..bc7e5b50e 100644
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -82,39 +82,41 @@ target_link_libraries(wallet
${EXTRA_LIBRARIES})
add_dependencies(wallet version)
-set(wallet_rpc_sources
- wallet_rpc_server.cpp)
+if (NOT BUILD_GUI_DEPS)
+ set(wallet_rpc_sources
+ wallet_rpc_server.cpp)
-set(wallet_rpc_headers)
+ set(wallet_rpc_headers)
-set(wallet_rpc_private_headers
- wallet_rpc_server.h)
+ set(wallet_rpc_private_headers
+ wallet_rpc_server.h)
-monero_private_headers(wallet_rpc_server
- ${wallet_rpc_private_headers})
-monero_add_executable(wallet_rpc_server
- ${wallet_rpc_sources}
- ${wallet_rpc_headers}
- ${wallet_rpc_private_headers})
+ monero_private_headers(wallet_rpc_server
+ ${wallet_rpc_private_headers})
+ monero_add_executable(wallet_rpc_server
+ ${wallet_rpc_sources}
+ ${wallet_rpc_headers}
+ ${wallet_rpc_private_headers})
-target_link_libraries(wallet_rpc_server
- PRIVATE
- wallet
- rpc
- cryptonote_core
- crypto
- common
- ${Boost_CHRONO_LIBRARY}
- ${Boost_PROGRAM_OPTIONS_LIBRARY}
- ${Boost_FILESYSTEM_LIBRARY}
- ${Boost_THREAD_LIBRARY}
- ${CMAKE_THREAD_LIBS_INIT}
- ${EXTRA_LIBRARIES})
-add_dependencies(wallet_rpc_server version)
-set_property(TARGET wallet_rpc_server
- PROPERTY
- OUTPUT_NAME "monero-wallet-rpc")
-install(TARGETS wallet_rpc_server DESTINATION bin)
+ target_link_libraries(wallet_rpc_server
+ PRIVATE
+ wallet
+ rpc
+ cryptonote_core
+ crypto
+ common
+ ${Boost_CHRONO_LIBRARY}
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${Boost_FILESYSTEM_LIBRARY}
+ ${Boost_THREAD_LIBRARY}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${EXTRA_LIBRARIES})
+ add_dependencies(wallet_rpc_server version)
+ set_property(TARGET wallet_rpc_server
+ PROPERTY
+ OUTPUT_NAME "monero-wallet-rpc")
+ install(TARGETS wallet_rpc_server DESTINATION bin)
+endif()
# build and install libwallet_merged only if we building for GUI
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 091439ce5..15a134257 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -631,11 +631,16 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
}
// Don't try to extract tx public key if tx has no ouputs
- if (!tx.vout.empty())
+ size_t pk_index = 0;
+ while (!tx.vout.empty())
{
+ // if tx.vout is not empty, we loop through all tx pubkeys
+
tx_extra_pub_key pub_key_field;
- if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field))
+ if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++))
{
+ if (pk_index > 1)
+ break;
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);
@@ -2961,6 +2966,7 @@ bool wallet2::save_tx(const std::vector<pending_tx>& ptx_vector, const std::stri
unsigned_tx_set txs;
for (auto &tx: ptx_vector)
txs.txes.push_back(tx.construction_data);
+ txs.transfers = m_transfers;
std::string s = obj_to_json_str(txs);
if (s.empty())
return false;
@@ -2971,7 +2977,7 @@ bool wallet2::save_tx(const std::vector<pending_tx>& ptx_vector, const std::stri
return epee::file_io_utils::save_string_to_file(filename, std::string(UNSIGNED_TX_PREFIX) + s);
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::function<bool(const unsigned_tx_set&)> accept_func)
+bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::vector<wallet2::pending_tx> &txs, std::function<bool(const unsigned_tx_set&)> accept_func)
{
std::string s;
boost::system::error_code errcode;
@@ -3006,6 +3012,8 @@ bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &s
return false;
}
+ import_outputs(exported_txs.transfers);
+
// sign the transactions
signed_tx_set signed_txes;
for (size_t n = 0; n < exported_txs.txes.size(); ++n)
@@ -3051,6 +3059,17 @@ bool wallet2::sign_tx(const std::string &unsigned_filename, const std::string &s
ptx.tx_key = rct::rct2sk(rct::identity()); // don't send it back to the untrusted view wallet
ptx.dests = sd.splitted_dsts;
ptx.construction_data = sd;
+
+ txs.push_back(ptx);
+ }
+
+ // add key images
+ signed_txes.key_images.resize(m_transfers.size());
+ for (size_t i = 0; i < m_transfers.size(); ++i)
+ {
+ if (!m_transfers[i].m_key_image_known)
+ LOG_PRINT_L0("WARNING: key image not known in signing wallet at index " << i);
+ signed_txes.key_images[i] = m_transfers[i].m_key_image;
}
s = obj_to_json_str(signed_txes);
@@ -3100,6 +3119,23 @@ bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wal
return false;
}
+ // import key images
+ if (signed_txs.key_images.size() > m_transfers.size())
+ {
+ LOG_PRINT_L1("More key images returned that we know outputs for");
+ return false;
+ }
+ for (size_t i = 0; i < signed_txs.key_images.size(); ++i)
+ {
+ transfer_details &td = m_transfers[i];
+ if (td.m_key_image_known && td.m_key_image != signed_txs.key_images[i])
+ LOG_PRINT_L0("WARNING: imported key image differs from previously known key image at index " << i << ": trusting imported one");
+ td.m_key_image = signed_txs.key_images[i];
+ m_key_images[m_transfers[i].m_key_image] = i;
+ td.m_key_image_known = true;
+ m_pub_keys[m_transfers[i].get_public_key()] = i;
+ }
+
ptx = signed_txs.ptx;
return true;
@@ -4745,6 +4781,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
for (size_t n = 0; n < signed_key_images.size(); ++n)
{
m_transfers[n].m_key_image = signed_key_images[n].first;
+ m_key_images[m_transfers[n].m_key_image] = n;
m_transfers[n].m_key_image_known = true;
}
@@ -4805,17 +4842,19 @@ size_t wallet2::import_outputs(const std::vector<tools::wallet2::transfer_detail
std::vector<tx_extra_field> tx_extra_fields;
tx_extra_pub_key pub_key_field;
- THROW_WALLET_EXCEPTION_IF(td.m_tx.vout.empty(), error::wallet_internal_error, "tx with no outputs at index " + i);
+ THROW_WALLET_EXCEPTION_IF(td.m_tx.vout.empty(), error::wallet_internal_error, "tx with no outputs at index " + boost::lexical_cast<std::string>(i));
THROW_WALLET_EXCEPTION_IF(!parse_tx_extra(td.m_tx.extra, tx_extra_fields), error::wallet_internal_error,
- "Transaction extra has unsupported format at index " + i);
+ "Transaction extra has unsupported format at index " + boost::lexical_cast<std::string>(i));
THROW_WALLET_EXCEPTION_IF(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field), error::wallet_internal_error,
- "Public key wasn't found in the transaction extra at index " + i);
+ "Public key wasn't found in the transaction extra at index " + boost::lexical_cast<std::string>(i));
cryptonote::generate_key_image_helper(m_account.get_keys(), pub_key_field.pub_key, td.m_internal_output_index, in_ephemeral, td.m_key_image);
td.m_key_image_known = true;
THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key,
- error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + i);
+ error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + boost::lexical_cast<std::string>(i));
+ m_key_images[td.m_key_image] = m_transfers.size();
+ m_pub_keys[td.get_public_key()] = m_transfers.size();
m_transfers.push_back(td);
}
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index cef218dd8..6168873d5 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -133,6 +133,21 @@ namespace tools
bool is_rct() const { return m_rct; }
uint64_t amount() const { return m_amount; }
const crypto::public_key &get_public_key() const { return boost::get<const cryptonote::txout_to_key>(m_tx.vout[m_internal_output_index].target).key; }
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(m_block_height)
+ FIELD(m_tx)
+ FIELD(m_txid)
+ FIELD(m_internal_output_index)
+ FIELD(m_global_output_index)
+ FIELD(m_spent)
+ FIELD(m_spent_height)
+ FIELD(m_key_image)
+ FIELD(m_mask)
+ FIELD(m_amount)
+ FIELD(m_rct)
+ FIELD(m_key_image_known)
+ END_SERIALIZE()
};
struct payment_details
@@ -226,16 +241,20 @@ namespace tools
struct unsigned_tx_set
{
std::vector<tx_construction_data> txes;
+ wallet2::transfer_container transfers;
BEGIN_SERIALIZE_OBJECT()
FIELD(txes)
+ FIELD(transfers)
END_SERIALIZE()
};
struct signed_tx_set
{
std::vector<pending_tx> ptx;
+ std::vector<crypto::key_image> key_images;
BEGIN_SERIALIZE_OBJECT()
FIELD(ptx)
+ FIELD(key_images)
END_SERIALIZE()
};
@@ -377,7 +396,7 @@ namespace tools
void commit_tx(pending_tx& ptx_vector);
void commit_tx(std::vector<pending_tx>& ptx_vector);
bool save_tx(const std::vector<pending_tx>& ptx_vector, const std::string &filename);
- bool sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::function<bool(const unsigned_tx_set&)> accept_func = NULL);
+ bool sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::vector<wallet2::pending_tx> &ptx, std::function<bool(const unsigned_tx_set&)> accept_func = NULL);
bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
std::vector<pending_tx> create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon);
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon);
@@ -614,7 +633,7 @@ namespace tools
};
}
BOOST_CLASS_VERSION(tools::wallet2, 15)
-BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 5)
+BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 6)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 6)
BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 3)
@@ -643,7 +662,10 @@ namespace boost
{
x.m_rct = x.m_tx.vout[x.m_internal_output_index].amount == 0;
}
- x.m_key_image_known = true;
+ if (ver < 6)
+ {
+ x.m_key_image_known = true;
+ }
}
template <class Archive>
@@ -692,7 +714,18 @@ namespace boost
}
a & x.m_rct;
if (ver < 5)
+ {
+ initialize_transfer_details(a, x, ver);
return;
+ }
+ if (ver < 6)
+ {
+ // v5 did not properly initialize
+ uint8_t u;
+ a & u;
+ x.m_key_image_known = true;
+ return;
+ }
a & x.m_key_image_known;
}