diff options
Diffstat (limited to 'src/wallet')
35 files changed, 858 insertions, 282 deletions
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 2991f75c5..efd61cb5a 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2019, The Monero Project # # All rights reserved. # diff --git a/src/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt index d6f2bf6b7..3376ec70e 100644 --- a/src/wallet/api/CMakeLists.txt +++ b/src/wallet/api/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2019, The Monero Project # # All rights reserved. # diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp index 7ef011e06..7be78bba7 100644 --- a/src/wallet/api/address_book.cpp +++ b/src/wallet/api/address_book.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/address_book.h b/src/wallet/api/address_book.h index f4ca68efd..92e6eaa17 100644 --- a/src/wallet/api/address_book.h +++ b/src/wallet/api/address_book.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp index 913e3156f..e649f1f3a 100644 --- a/src/wallet/api/pending_transaction.cpp +++ b/src/wallet/api/pending_transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h index 50b9f07ef..4ec7c656a 100644 --- a/src/wallet/api/pending_transaction.h +++ b/src/wallet/api/pending_transaction.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress.cpp b/src/wallet/api/subaddress.cpp index 61dbbf4b0..8a1d34864 100644 --- a/src/wallet/api/subaddress.cpp +++ b/src/wallet/api/subaddress.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress.h b/src/wallet/api/subaddress.h index f3db7d97b..87585ec16 100644 --- a/src/wallet/api/subaddress.h +++ b/src/wallet/api/subaddress.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress_account.cpp b/src/wallet/api/subaddress_account.cpp index 4765465c3..9bc9d1d91 100644 --- a/src/wallet/api/subaddress_account.cpp +++ b/src/wallet/api/subaddress_account.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/subaddress_account.h b/src/wallet/api/subaddress_account.h index b052182f8..358e446d4 100644 --- a/src/wallet/api/subaddress_account.h +++ b/src/wallet/api/subaddress_account.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index ba46a6904..f4ad8b1f6 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h index 7bdce97e2..67fe1989d 100644 --- a/src/wallet/api/transaction_history.h +++ b/src/wallet/api/transaction_history.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp index cc3209609..21573c6f6 100644 --- a/src/wallet/api/transaction_info.cpp +++ b/src/wallet/api/transaction_info.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h index 37e0445d9..d5c8f31cf 100644 --- a/src/wallet/api/transaction_info.h +++ b/src/wallet/api/transaction_info.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp index 29910a3b6..c2c04cbc3 100644 --- a/src/wallet/api/unsigned_transaction.cpp +++ b/src/wallet/api/unsigned_transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h index 8a3330014..f1af80fa1 100644 --- a/src/wallet/api/unsigned_transaction.h +++ b/src/wallet/api/unsigned_transaction.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/utils.cpp b/src/wallet/api/utils.cpp index 86fe56564..24252868a 100644 --- a/src/wallet/api/utils.cpp +++ b/src/wallet/api/utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 935a8d51c..da6ddc8a3 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -1504,7 +1504,6 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction() { clearStatus(); - vector<cryptonote::tx_destination_entry> dsts; cryptonote::tx_destination_entry de; PendingTransactionImpl * transaction = new PendingTransactionImpl(*this); @@ -1924,7 +1923,7 @@ bool WalletImpl::verifyMessageWithPublicKey(const std::string &message, const st bool WalletImpl::connectToDaemon() { - bool result = m_wallet->check_connection(NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS); + bool result = m_wallet->check_connection(NULL, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS); if (!result) { setStatusError("Error connecting to daemon at " + m_wallet->get_daemon_address()); } else { @@ -1937,7 +1936,7 @@ bool WalletImpl::connectToDaemon() Wallet::ConnectionStatus WalletImpl::connected() const { uint32_t version = 0; - m_is_connected = m_wallet->check_connection(&version, DEFAULT_CONNECTION_TIMEOUT_MILLIS); + m_is_connected = m_wallet->check_connection(&version, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS); if (!m_is_connected) return Wallet::ConnectionStatus_Disconnected; // Version check is not implemented in light wallets nodes/wallets diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 55240d64f..bd33b773c 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index 5c301974f..c549c260b 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 89fe01c0d..f584e88ac 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index b3c0d6c00..0c83d794f 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/message_transporter.cpp b/src/wallet/message_transporter.cpp index eafd13d3b..2f8188a3c 100644 --- a/src/wallet/message_transporter.cpp +++ b/src/wallet/message_transporter.cpp @@ -44,7 +44,7 @@ namespace mms namespace bitmessage_rpc { - struct message_info + struct message_info_t { uint32_t encodingType; std::string toAddress; @@ -66,8 +66,9 @@ namespace bitmessage_rpc KV_SERIALIZE(subject) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<message_info_t> message_info; - struct inbox_messages_response + struct inbox_messages_response_t { std::vector<message_info> inboxMessages; @@ -75,6 +76,7 @@ namespace bitmessage_rpc KV_SERIALIZE(inboxMessages) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<inbox_messages_response_t> inbox_messages_response; } @@ -116,7 +118,11 @@ bool message_transporter::receive_messages(const std::vector<std::string> &desti std::string json = get_str_between_tags(answer, "<string>", "</string>"); bitmessage_rpc::inbox_messages_response bitmessage_res; - epee::serialization::load_t_from_json(bitmessage_res, json); + if (!epee::serialization::load_t_from_json(bitmessage_res, json)) + { + MERROR("Failed to deserialize messages"); + return true; + } size_t size = bitmessage_res.inboxMessages.size(); messages.clear(); @@ -138,8 +144,10 @@ bool message_transporter::receive_messages(const std::vector<std::string> &desti std::string message_body = epee::string_encoding::base64_decode(message_info.message); // Second Base64-decoding: The MMS uses Base64 to hide non-textual data in its JSON from Bitmessage json = epee::string_encoding::base64_decode(message_body); - epee::serialization::load_t_from_json(message, json); - is_mms_message = true; + if (!epee::serialization::load_t_from_json(message, json)) + MERROR("Failed to deserialize message"); + else + is_mms_message = true; } catch(const std::exception& e) { diff --git a/src/wallet/message_transporter.h b/src/wallet/message_transporter.h index 8291311ce..736fc9b63 100644 --- a/src/wallet/message_transporter.h +++ b/src/wallet/message_transporter.h @@ -42,7 +42,7 @@ namespace mms { -struct transport_message +struct transport_message_t { cryptonote::account_public_address source_monero_address; std::string source_transport_address; @@ -78,6 +78,7 @@ struct transport_message KV_SERIALIZE(transport_id) END_KV_SERIALIZE_MAP() }; +typedef epee::misc_utils::struct_init<transport_message_t> transport_message; class message_transporter { diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index 605531e59..f5f3c0e1b 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h index 65f13eaaa..3630aec08 100644 --- a/src/wallet/node_rpc_proxy.h +++ b/src/wallet/node_rpc_proxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index af8dbb16d..8bb886c6d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -237,6 +237,12 @@ struct options { const command_line::arg_descriptor<std::string> password_file = {"password-file", tools::wallet2::tr("Wallet password file"), "", true}; const command_line::arg_descriptor<int> daemon_port = {"daemon-port", tools::wallet2::tr("Use daemon instance at port <arg> instead of 18081"), 0}; const command_line::arg_descriptor<std::string> daemon_login = {"daemon-login", tools::wallet2::tr("Specify username[:password] for daemon RPC client"), "", true}; + const command_line::arg_descriptor<std::string> daemon_ssl = {"daemon-ssl", tools::wallet2::tr("Enable SSL on daemon RPC connections: enabled|disabled|autodetect"), "autodetect"}; + const command_line::arg_descriptor<std::string> daemon_ssl_private_key = {"daemon-ssl-private-key", tools::wallet2::tr("Path to a PEM format private key"), ""}; + const command_line::arg_descriptor<std::string> daemon_ssl_certificate = {"daemon-ssl-certificate", tools::wallet2::tr("Path to a PEM format certificate"), ""}; + const command_line::arg_descriptor<std::vector<std::string>> daemon_ssl_allowed_certificates = {"daemon-ssl-allowed-certificates", tools::wallet2::tr("List of paths to PEM format certificates of allowed RPC servers")}; + const command_line::arg_descriptor<std::vector<std::string>> daemon_ssl_allowed_fingerprints = {"daemon-ssl-allowed-fingerprints", tools::wallet2::tr("List of valid fingerprints of allowed RPC servers")}; + const command_line::arg_descriptor<bool> daemon_ssl_allow_any_cert = {"daemon-ssl-allow-any-cert", tools::wallet2::tr("Allow any SSL certificate from the daemon"), false}; const command_line::arg_descriptor<bool> testnet = {"testnet", tools::wallet2::tr("For testnet. Daemon must also be launched with --testnet flag"), false}; const command_line::arg_descriptor<bool> stagenet = {"stagenet", tools::wallet2::tr("For stagenet. Daemon must also be launched with --stagenet flag"), false}; const command_line::arg_descriptor<std::string, false, true, 2> shared_ringdb_dir = { @@ -308,6 +314,15 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl auto daemon_port = command_line::get_arg(vm, opts.daemon_port); auto device_name = command_line::get_arg(vm, opts.hw_device); auto device_derivation_path = command_line::get_arg(vm, opts.hw_device_derivation_path); + auto daemon_ssl_private_key = command_line::get_arg(vm, opts.daemon_ssl_private_key); + auto daemon_ssl_certificate = command_line::get_arg(vm, opts.daemon_ssl_certificate); + auto daemon_ssl_allowed_certificates = command_line::get_arg(vm, opts.daemon_ssl_allowed_certificates); + auto daemon_ssl_allowed_fingerprints = command_line::get_arg(vm, opts.daemon_ssl_allowed_fingerprints); + auto daemon_ssl_allow_any_cert = command_line::get_arg(vm, opts.daemon_ssl_allow_any_cert); + auto daemon_ssl = command_line::get_arg(vm, opts.daemon_ssl); + epee::net_utils::ssl_support_t ssl_support; + THROW_WALLET_EXCEPTION_IF(!epee::net_utils::ssl_support_from_string(ssl_support, daemon_ssl), tools::error::wallet_internal_error, + tools::wallet2::tr("Invalid argument for ") + std::string(opts.daemon_ssl.name)); THROW_WALLET_EXCEPTION_IF(!daemon_address.empty() && !daemon_host.empty() && 0 != daemon_port, tools::error::wallet_internal_error, tools::wallet2::tr("can't specify daemon host or port more than once")); @@ -358,8 +373,23 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl catch (const std::exception &e) { } } + std::list<std::string> ssl_allowed_certificates; + for (const std::string &path: daemon_ssl_allowed_certificates) + { + ssl_allowed_certificates.push_back({}); + if (!epee::file_io_utils::load_file_to_string(path, ssl_allowed_certificates.back())) + { + MERROR("Failed to load certificate: " << path); + ssl_allowed_certificates.back() = std::string(); + } + } + + std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints{ daemon_ssl_allowed_fingerprints.size() }; + std::transform(daemon_ssl_allowed_fingerprints.begin(), daemon_ssl_allowed_fingerprints.end(), ssl_allowed_fingerprints.begin(), epee::from_hex::vector); + std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, kdf_rounds, unattended)); - wallet->init(std::move(daemon_address), std::move(login), 0, false, *trusted_daemon); + wallet->init(std::move(daemon_address), std::move(login), 0, *trusted_daemon, ssl_support, std::make_pair(daemon_ssl_private_key, daemon_ssl_certificate), ssl_allowed_certificates, ssl_allowed_fingerprints, daemon_ssl_allow_any_cert); + boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir); wallet->set_ring_database(ringdb_path.string()); wallet->get_message_store().set_options(vm); @@ -373,7 +403,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl } catch (const std::exception &e) { - MERROR("Failed to parse tx notify spec"); + MERROR("Failed to parse tx notify spec: " << e.what()); } return wallet; @@ -763,9 +793,8 @@ uint64_t calculate_fee(bool use_per_byte_fee, const cryptonote::transaction &tx, return calculate_fee(base_fee, blob_size, fee_multiplier); } -crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::device &hwdev) +bool get_short_payment_id(crypto::hash8 &payment_id8, const tools::wallet2::pending_tx &ptx, hw::device &hwdev) { - crypto::hash8 payment_id8 = null_hash8; std::vector<tx_extra_field> tx_extra_fields; parse_tx_extra(ptx.tx.extra, tx_extra_fields); // ok if partially parsed cryptonote::tx_extra_nonce extra_nonce; @@ -776,19 +805,19 @@ crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::de if (ptx.dests.empty()) { MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt"); - return crypto::null_hash8; + return false; } - hwdev.decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key); + return hwdev.decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key); } } - return payment_id8; + return false; } tools::wallet2::tx_construction_data get_construction_data_with_decrypted_short_payment_id(const tools::wallet2::pending_tx &ptx, hw::device &hwdev) { tools::wallet2::tx_construction_data construction_data = ptx.construction_data; - crypto::hash8 payment_id = get_short_payment_id(ptx,hwdev); - if (payment_id != null_hash8) + crypto::hash8 payment_id = null_hash8; + if (get_short_payment_id(payment_id, ptx, hwdev)) { // Remove encrypted remove_field_from_tx_extra(construction_data.extra, typeid(cryptonote::tx_extra_nonce)); @@ -867,7 +896,7 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional<too w(w), locked(password != boost::none) { - if (!locked || w.is_unattended() || w.ask_password() != tools::wallet2::AskPasswordToDecrypt) + if (!locked || w.is_unattended() || w.ask_password() != tools::wallet2::AskPasswordToDecrypt || w.watch_only()) { locked = false; return; @@ -1015,6 +1044,12 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.password_file); command_line::add_arg(desc_params, opts.daemon_port); command_line::add_arg(desc_params, opts.daemon_login); + command_line::add_arg(desc_params, opts.daemon_ssl); + command_line::add_arg(desc_params, opts.daemon_ssl_private_key); + command_line::add_arg(desc_params, opts.daemon_ssl_certificate); + command_line::add_arg(desc_params, opts.daemon_ssl_allowed_certificates); + command_line::add_arg(desc_params, opts.daemon_ssl_allowed_fingerprints); + command_line::add_arg(desc_params, opts.daemon_ssl_allow_any_cert); command_line::add_arg(desc_params, opts.testnet); command_line::add_arg(desc_params, opts.stagenet); command_line::add_arg(desc_params, opts.shared_ringdb_dir); @@ -1066,7 +1101,7 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia } //---------------------------------------------------------------------------------------------------- -bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_weight_limit, bool ssl, bool trusted_daemon) +bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_weight_limit, bool trusted_daemon, epee::net_utils::ssl_support_t ssl_support, const std::pair<std::string, std::string> &private_key_and_certificate_path, const std::list<std::string> &allowed_certificates, const std::vector<std::vector<uint8_t>> &allowed_fingerprints, bool allow_any_cert) { m_checkpoints.init_default_checkpoints(m_nettype); if(m_http_client.is_connected()) @@ -1076,8 +1111,7 @@ bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils:: m_daemon_address = std::move(daemon_address); m_daemon_login = std::move(daemon_login); m_trusted_daemon = trusted_daemon; - // When switching from light wallet to full wallet, we need to reset the height we got from lw node. - return m_http_client.set_server(get_daemon_address(), get_daemon_login(), ssl); + return m_http_client.set_server(get_daemon_address(), get_daemon_login(), ssl_support, private_key_and_certificate_path, allowed_certificates, allowed_fingerprints, allow_any_cert); } //---------------------------------------------------------------------------------------------------- bool wallet2::is_deterministic() const @@ -1426,7 +1460,7 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation & } } //---------------------------------------------------------------------------------------------------- -void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool) +void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool) { THROW_WALLET_EXCEPTION_IF(i >= tx.vout.size(), error::wallet_internal_error, "Invalid vout index"); @@ -1459,11 +1493,20 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key"); } - outs.push_back(i); - if (tx_scan_info.money_transfered == 0) + THROW_WALLET_EXCEPTION_IF(std::find(outs.begin(), outs.end(), i) != outs.end(), error::wallet_internal_error, "Same output cannot be added twice"); + if (tx_scan_info.money_transfered == 0 && !miner_tx) { tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask, m_account.get_device()); } + if (tx_scan_info.money_transfered == 0) + { + MERROR("Invalid output amount, skipping"); + tx_scan_info.error = true; + return; + } + outs.push_back(i); + THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs[tx_scan_info.received->index] >= std::numeric_limits<uint64_t>::max() - tx_scan_info.money_transfered, + error::wallet_internal_error, "Overflow in received amounts"); tx_money_got_in_outs[tx_scan_info.received->index] += tx_scan_info.money_transfered; tx_scan_info.amount = tx_scan_info.money_transfered; ++num_vouts_received; @@ -1496,7 +1539,6 @@ void wallet2::cache_tx_data(const cryptonote::transaction& tx, const crypto::has // additional tx pubkeys and derivations for multi-destination transfers involving one or more subaddresses tx_extra_additional_pub_keys additional_tx_pub_keys; - std::vector<crypto::key_derivation> additional_derivations; if (find_tx_extra_field_by_type(tx_cache_data.tx_extra_fields, additional_tx_pub_keys)) { for (size_t i = 0; i < additional_tx_pub_keys.data.size(); ++i) @@ -1641,7 +1683,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote if (tx_scan_info[i].received) { hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations); - scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool); + scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool); } } } @@ -1664,7 +1706,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote if (tx_scan_info[i].received) { hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations); - scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool); + scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool); } } } @@ -1680,7 +1722,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote boost::unique_lock<hw::device> hwdev_lock (hwdev); hwdev.set_mode(hw::device::NONE); hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys.data, derivation, additional_derivations); - scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool); + scan_output(tx, miner_tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs, pool); } } } @@ -2969,6 +3011,11 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo { LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")..."); first = true; + start_height = 0; + blocks.clear(); + parsed_blocks.clear(); + short_chain_history.clear(); + get_short_chain_history(short_chain_history, 1); ++try_count; } else @@ -4848,7 +4895,7 @@ bool wallet2::prepare_file_names(const std::string& file_path) return true; } //---------------------------------------------------------------------------------------------------- -bool wallet2::check_connection(uint32_t *version, uint32_t timeout) +bool wallet2::check_connection(uint32_t *version, bool *ssl, uint32_t timeout) { THROW_WALLET_EXCEPTION_IF(!m_is_initialized, error::wallet_not_initialized); @@ -4856,15 +4903,20 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout) // TODO: Add light wallet version check. if(m_light_wallet) { - version = 0; + if (version) + *version = 0; + if (ssl) + *ssl = m_light_wallet_connected; // light wallet is always SSL return m_light_wallet_connected; } - if(!m_http_client.is_connected()) + if(!m_http_client.is_connected(ssl)) { m_node_rpc_proxy.invalidate(); if (!m_http_client.connect(std::chrono::milliseconds(timeout))) return false; + if(!m_http_client.is_connected(ssl)) + return false; } if (version) @@ -10135,11 +10187,11 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de else { cryptonote::blobdata tx_data; - crypto::hash tx_prefix_hash; ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data); THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon"); - THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx, tx_hash, tx_prefix_hash), + THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx), error::wallet_internal_error, "Failed to validate transaction from daemon"); + tx_hash = cryptonote::get_transaction_hash(tx); } THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error, @@ -10281,11 +10333,11 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac else { cryptonote::blobdata tx_data; - crypto::hash tx_prefix_hash; ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data); THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon"); - THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx, tx_hash, tx_prefix_hash), + THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx), error::wallet_internal_error, "Failed to validate transaction from daemon"); + tx_hash = cryptonote::get_transaction_hash(tx); } THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error, "Failed to get the right transaction from daemon"); @@ -10399,11 +10451,11 @@ bool wallet2::check_tx_proof(const crypto::hash &txid, const cryptonote::account else { cryptonote::blobdata tx_data; - crypto::hash tx_prefix_hash; ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data); THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon"); - THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx, tx_hash, tx_prefix_hash), + THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx), error::wallet_internal_error, "Failed to validate transaction from daemon"); + tx_hash = cryptonote::get_transaction_hash(tx); } THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error, "Failed to get the right transaction from daemon"); @@ -11309,6 +11361,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); } size_t output_index = 0; + bool miner_tx = cryptonote::is_coinbase(spent_tx); for (const cryptonote::tx_out& out : spent_tx.vout) { tx_scan_info_t tx_scan_info; @@ -11316,11 +11369,13 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag THROW_WALLET_EXCEPTION_IF(tx_scan_info.error, error::wallet_internal_error, "check_acc_out_precomp failed"); if (tx_scan_info.received) { - if (tx_scan_info.money_transfered == 0) + if (tx_scan_info.money_transfered == 0 && !miner_tx) { rct::key mask; tx_scan_info.money_transfered = tools::decodeRct(spent_tx.rct_signatures, tx_scan_info.received->derivation, output_index, mask, hwdev); } + THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs >= std::numeric_limits<uint64_t>::max() - tx_scan_info.money_transfered, + error::wallet_internal_error, "Overflow in received amounts"); tx_money_got_in_outs += tx_scan_info.money_transfered; } ++output_index; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 3b2dd6076..36271c82a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -67,6 +67,7 @@ #define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2" class Serialization_portability_wallet_Test; +class wallet_accessor_test; namespace tools { @@ -171,6 +172,7 @@ namespace tools class wallet2 { friend class ::Serialization_portability_wallet_Test; + friend class ::wallet_accessor_test; friend class wallet_keys_unlocker; friend class wallet_device_callback; public: @@ -676,7 +678,12 @@ namespace tools bool deinit(); bool init(std::string daemon_address = "http://localhost:8080", - boost::optional<epee::net_utils::http::login> daemon_login = boost::none, uint64_t upper_transaction_weight_limit = 0, bool ssl = false, bool trusted_daemon = false); + boost::optional<epee::net_utils::http::login> daemon_login = boost::none, uint64_t upper_transaction_weight_limit = 0, + bool trusted_daemon = true, + epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, + const std::pair<std::string, std::string> &private_key_and_certificate_path = {}, + const std::list<std::string> &allowed_certificates = {}, const std::vector<std::vector<uint8_t>> &allowed_fingerprints = {}, + bool allow_any_cert = false); void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); } @@ -800,7 +807,7 @@ namespace tools bool sign_multisig_tx_to_file(multisig_tx_set &exported_txs, const std::string &filename, std::vector<crypto::hash> &txids); std::vector<pending_tx> create_unmixable_sweep_transactions(); void discard_unmixable_outputs(); - bool check_connection(uint32_t *version = NULL, uint32_t timeout = 200000); + bool check_connection(uint32_t *version = NULL, bool *ssl = NULL, uint32_t timeout = 200000); void get_transfers(wallet2::transfer_container& incoming_transfers) const; void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments, uint64_t min_height = 0, const boost::optional<uint32_t>& subaddr_account = boost::none, const std::set<uint32_t>& subaddr_indices = {}) const; void get_payments(std::list<std::pair<crypto::hash,wallet2::payment_details>>& payments, uint64_t min_height, uint64_t max_height = (uint64_t)-1, const boost::optional<uint32_t>& subaddr_account = boost::none, const std::set<uint32_t>& subaddr_indices = {}) const; @@ -1292,7 +1299,7 @@ namespace tools bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const; bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const; std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const; - void scan_output(const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool); + void scan_output(const cryptonote::transaction &tx, bool miner_tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool); void trim_hashchain(); crypto::key_image get_multisig_composite_key_image(size_t n) const; rct::multisig_kLRki get_multisig_composite_kLRki(size_t n, const std::unordered_set<crypto::public_key> &ignore_set, std::unordered_set<rct::key> &used_L, std::unordered_set<rct::key> &new_used_L) const; diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index b9d0a6a75..a4bb342ca 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_args.h b/src/wallet/wallet_args.h index a1f251144..c861dca11 100644 --- a/src/wallet/wallet_args.h +++ b/src/wallet/wallet_args.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 78e62c67e..6ebaaa395 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index c87c2fca6..5b7cf90d0 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -63,6 +63,11 @@ namespace const command_line::arg_descriptor<bool> arg_restricted = {"restricted-rpc", "Restricts to view-only commands", false}; const command_line::arg_descriptor<std::string> arg_wallet_dir = {"wallet-dir", "Directory for newly created wallets"}; const command_line::arg_descriptor<bool> arg_prompt_for_password = {"prompt-for-password", "Prompts for password when not provided", false}; + const command_line::arg_descriptor<std::string> arg_rpc_ssl = {"rpc-ssl", tools::wallet2::tr("Enable SSL on wallet RPC connections: enabled|disabled|autodetect"), "autodetect"}; + const command_line::arg_descriptor<std::string> arg_rpc_ssl_private_key = {"rpc-ssl-private-key", tools::wallet2::tr("Path to a PEM format private key"), ""}; + const command_line::arg_descriptor<std::string> arg_rpc_ssl_certificate = {"rpc-ssl-certificate", tools::wallet2::tr("Path to a PEM format certificate"), ""}; + const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_certificates = {"rpc-ssl-allowed-certificates", tools::wallet2::tr("List of paths to PEM format certificates of allowed RPC servers (all allowed if empty)")}; + const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_fingerprints = {"rpc-ssl-allowed-fingerprints", tools::wallet2::tr("List of certificate fingerprints to allow")}; constexpr const char default_rpc_username[] = "monero"; @@ -233,10 +238,36 @@ namespace tools assert(bool(http_login)); } // end auth enabled + auto rpc_ssl_private_key = command_line::get_arg(vm, arg_rpc_ssl_private_key); + auto rpc_ssl_certificate = command_line::get_arg(vm, arg_rpc_ssl_certificate); + auto rpc_ssl_allowed_certificates = command_line::get_arg(vm, arg_rpc_ssl_allowed_certificates); + auto rpc_ssl_allowed_fingerprints = command_line::get_arg(vm, arg_rpc_ssl_allowed_fingerprints); + auto rpc_ssl = command_line::get_arg(vm, arg_rpc_ssl); + epee::net_utils::ssl_support_t rpc_ssl_support; + if (!epee::net_utils::ssl_support_from_string(rpc_ssl_support, rpc_ssl)) + { + MERROR("Invalid argument for " << std::string(arg_rpc_ssl.name)); + return false; + } + std::list<std::string> allowed_certificates; + for (const std::string &path: rpc_ssl_allowed_certificates) + { + allowed_certificates.push_back({}); + if (!epee::file_io_utils::load_file_to_string(path, allowed_certificates.back())) + { + MERROR("Failed to load certificate: " << path); + allowed_certificates.back() = std::string(); + } + } + + std::vector<std::vector<uint8_t>> allowed_fingerprints{ rpc_ssl_allowed_fingerprints.size() }; + std::transform(rpc_ssl_allowed_fingerprints.begin(), rpc_ssl_allowed_fingerprints.end(), allowed_fingerprints.begin(), epee::from_hex::vector); + m_net_server.set_threads_prefix("RPC"); auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); }; return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init( - rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) + rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login), + rpc_ssl_support, std::make_pair(rpc_ssl_private_key, rpc_ssl_certificate), std::move(allowed_certificates), std::move(allowed_fingerprints) ); } //------------------------------------------------------------------------------------------------------------------------------ @@ -337,30 +368,54 @@ namespace tools if (!m_wallet) return not_open(er); try { - res.balance = m_wallet->balance(req.account_index); - res.unlocked_balance = m_wallet->unlocked_balance(req.account_index); + res.balance = req.all_accounts ? m_wallet->balance_all() : m_wallet->balance(req.account_index); + res.unlocked_balance = req.all_accounts ? m_wallet->unlocked_balance_all() : m_wallet->unlocked_balance(req.account_index); res.multisig_import_needed = m_wallet->multisig() && m_wallet->has_multisig_partial_key_images(); - std::map<uint32_t, uint64_t> balance_per_subaddress = m_wallet->balance_per_subaddress(req.account_index); - std::map<uint32_t, uint64_t> unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(req.account_index); - std::vector<tools::wallet2::transfer_details> transfers; - m_wallet->get_transfers(transfers); - std::set<uint32_t> address_indices = req.address_indices; - if (address_indices.empty()) + std::map<uint32_t, std::map<uint32_t, uint64_t>> balance_per_subaddress_per_account; + std::map<uint32_t, std::map<uint32_t, uint64_t>> unlocked_balance_per_subaddress_per_account; + if (req.all_accounts) { - for (const auto& i : balance_per_subaddress) - address_indices.insert(i.first); + for (uint32_t account_index = 0; account_index < m_wallet->get_num_subaddress_accounts(); ++account_index) + { + balance_per_subaddress_per_account[account_index] = m_wallet->balance_per_subaddress(account_index); + unlocked_balance_per_subaddress_per_account[account_index] = m_wallet->unlocked_balance_per_subaddress(account_index); + } } - for (uint32_t i : address_indices) + else { - wallet_rpc::COMMAND_RPC_GET_BALANCE::per_subaddress_info info; - info.address_index = i; - cryptonote::subaddress_index index = {req.account_index, info.address_index}; - info.address = m_wallet->get_subaddress_as_str(index); - info.balance = balance_per_subaddress[i]; - info.unlocked_balance = unlocked_balance_per_subaddress[i]; - info.label = m_wallet->get_subaddress_label(index); - info.num_unspent_outputs = std::count_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return !td.m_spent && td.m_subaddr_index == index; }); - res.per_subaddress.push_back(info); + balance_per_subaddress_per_account[req.account_index] = m_wallet->balance_per_subaddress(req.account_index); + unlocked_balance_per_subaddress_per_account[req.account_index] = m_wallet->unlocked_balance_per_subaddress(req.account_index); + } + std::vector<tools::wallet2::transfer_details> transfers; + m_wallet->get_transfers(transfers); + for (const auto& p : balance_per_subaddress_per_account) + { + uint32_t account_index = p.first; + std::map<uint32_t, uint64_t> balance_per_subaddress = p.second; + std::map<uint32_t, uint64_t> unlocked_balance_per_subaddress = unlocked_balance_per_subaddress_per_account[account_index]; + std::set<uint32_t> address_indices; + if (!req.all_accounts && !req.address_indices.empty()) + { + address_indices = req.address_indices; + } + else + { + for (const auto& i : balance_per_subaddress) + address_indices.insert(i.first); + } + for (uint32_t i : address_indices) + { + wallet_rpc::COMMAND_RPC_GET_BALANCE::per_subaddress_info info; + info.account_index = account_index; + info.address_index = i; + cryptonote::subaddress_index index = {info.account_index, info.address_index}; + info.address = m_wallet->get_subaddress_as_str(index); + info.balance = balance_per_subaddress[i]; + info.unlocked_balance = unlocked_balance_per_subaddress[i]; + info.label = m_wallet->get_subaddress_label(index); + info.num_unspent_outputs = std::count_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return !td.m_spent && td.m_subaddr_index == index; }); + res.per_subaddress.emplace_back(std::move(info)); + } } } catch (const std::exception& e) @@ -691,13 +746,9 @@ namespace tools if (wallet2::parse_long_payment_id(payment_id_str, long_payment_id)) { cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, long_payment_id); } - /* or short payment ID */ - else if (wallet2::parse_short_payment_id(payment_id_str, short_payment_id)) { - cryptonote::set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, short_payment_id); - } else { er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; - er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 16 or 64 character string"; + er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 64 character string"; return false; } @@ -1638,23 +1689,14 @@ namespace tools cryptonote::blobdata payment_id_blob; // TODO - should the whole thing fail because of one bad id? - - if(!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_blob)) - { - er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; - er.message = "Payment ID has invalid format: " + payment_id_str; - return false; - } - - if(sizeof(payment_id) == payment_id_blob.size()) + bool r; + if (payment_id_str.size() == 2 * sizeof(payment_id)) { - payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_blob.data()); + r = epee::string_tools::hex_to_pod(payment_id_str, payment_id); } - else if(sizeof(payment_id8) == payment_id_blob.size()) + else if (payment_id_str.size() == 2 * sizeof(payment_id8)) { - payment_id8 = *reinterpret_cast<const crypto::hash8*>(payment_id_blob.data()); - memcpy(payment_id.data, payment_id8.data, 8); - memset(payment_id.data + 8, 0, 24); + r = epee::string_tools::hex_to_pod(payment_id_str, payment_id8); } else { @@ -1663,6 +1705,13 @@ namespace tools return false; } + if(!r) + { + er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; + er.message = "Payment ID has invalid format: " + payment_id_str; + return false; + } + std::list<wallet2::payment_details> payment_list; m_wallet->get_payments(payment_id, payment_list, req.min_block_height); @@ -2146,9 +2195,6 @@ namespace tools try { - uint64_t received; - bool in_pool; - uint64_t confirmations; res.good = m_wallet->check_tx_proof(txid, info.address, info.is_subaddress, req.message, req.signature, res.received, res.in_pool, res.confirmations); } catch (const std::exception &e) @@ -2287,10 +2333,18 @@ namespace tools max_height = req.max_height <= max_height ? req.max_height : max_height; } + boost::optional<uint32_t> account_index = req.account_index; + std::set<uint32_t> subaddr_indices = req.subaddr_indices; + if (req.all_accounts) + { + account_index = boost::none; + subaddr_indices.clear(); + } + if (req.in) { std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments; - m_wallet->get_payments(payments, min_height, max_height, req.account_index, req.subaddr_indices); + m_wallet->get_payments(payments, min_height, max_height, account_index, subaddr_indices); for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { res.in.push_back(wallet_rpc::transfer_entry()); fill_transfer_entry(res.in.back(), i->second.m_tx_hash, i->first, i->second); @@ -2300,7 +2354,7 @@ namespace tools if (req.out) { std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments; - m_wallet->get_payments_out(payments, min_height, max_height, req.account_index, req.subaddr_indices); + m_wallet->get_payments_out(payments, min_height, max_height, account_index, subaddr_indices); for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { res.out.push_back(wallet_rpc::transfer_entry()); fill_transfer_entry(res.out.back(), i->first, i->second); @@ -2309,7 +2363,7 @@ namespace tools if (req.pending || req.failed) { std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments; - m_wallet->get_unconfirmed_payments_out(upayments, req.account_index, req.subaddr_indices); + m_wallet->get_unconfirmed_payments_out(upayments, account_index, subaddr_indices); for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) { const tools::wallet2::unconfirmed_transfer_details &pd = i->second; bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed; @@ -2326,7 +2380,7 @@ namespace tools m_wallet->update_pool_state(); std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> payments; - m_wallet->get_unconfirmed_payments(payments, req.account_index, req.subaddr_indices); + m_wallet->get_unconfirmed_payments(payments, account_index, subaddr_indices); for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { res.pool.push_back(wallet_rpc::transfer_entry()); fill_transfer_entry(res.pool.back(), i->first, i->second); @@ -2537,23 +2591,19 @@ namespace tools ski.resize(req.signed_key_images.size()); for (size_t n = 0; n < ski.size(); ++n) { - cryptonote::blobdata bd; - - if(!epee::string_tools::parse_hexstr_to_binbuff(req.signed_key_images[n].key_image, bd) || bd.size() != sizeof(crypto::key_image)) + if (!epee::string_tools::hex_to_pod(req.signed_key_images[n].key_image, ski[n].first)) { er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY_IMAGE; er.message = "failed to parse key image"; return false; } - ski[n].first = *reinterpret_cast<const crypto::key_image*>(bd.data()); - if(!epee::string_tools::parse_hexstr_to_binbuff(req.signed_key_images[n].signature, bd) || bd.size() != sizeof(crypto::signature)) + if (!epee::string_tools::hex_to_pod(req.signed_key_images[n].signature, ski[n].second)) { er.code = WALLET_RPC_ERROR_CODE_WRONG_SIGNATURE; er.message = "failed to parse signature"; return false; } - ski[n].second = *reinterpret_cast<const crypto::signature*>(bd.data()); } uint64_t spent = 0, unspent = 0; uint64_t height = m_wallet->import_key_images(ski, req.offset, spent, unspent); @@ -2857,8 +2907,6 @@ namespace tools std::vector<std::string> languages; crypto::ElectrumWords::get_language_list(languages); std::vector<std::string>::iterator it; - std::string wallet_file; - char *ptr; it = std::find(languages.begin(), languages.end(), req.language); if (it == languages.end()) @@ -3129,6 +3177,174 @@ namespace tools } } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) + { + if (m_wallet_dir.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR; + er.message = "No wallet dir configured"; + return false; + } + + // early check for mandatory fields + if (req.filename.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'filename' is mandatory. Please provide a filename to save the restored wallet to."; + return false; + } + if (req.viewkey.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'viewkey' is mandatory. Please provide a view key you want to restore from."; + return false; + } + if (req.address.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'address' is mandatory. Please provide a public address."; + return false; + } + + namespace po = boost::program_options; + po::variables_map vm2; + const char *ptr = strchr(req.filename.c_str(), '/'); + #ifdef _WIN32 + if (!ptr) + ptr = strchr(req.filename.c_str(), '\\'); + if (!ptr) + ptr = strchr(req.filename.c_str(), ':'); + #endif + if (ptr) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Invalid filename"; + return false; + } + std::string wallet_file = m_wallet_dir + "/" + req.filename; + // check if wallet file already exists + if (!wallet_file.empty()) + { + try + { + boost::system::error_code ignored_ec; + THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(wallet_file, ignored_ec), error::file_exists, wallet_file); + } + catch (const std::exception &e) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Wallet already exists."; + return false; + } + } + + { + po::options_description desc("dummy"); + const command_line::arg_descriptor<std::string, true> arg_password = {"password", "password"}; + const char *argv[4]; + int argc = 3; + argv[0] = "wallet-rpc"; + argv[1] = "--password"; + argv[2] = req.password.c_str(); + argv[3] = NULL; + vm2 = *m_vm; + command_line::add_arg(desc, arg_password); + po::store(po::parse_command_line(argc, argv, desc), vm2); + } + + auto rc = tools::wallet2::make_new(vm2, true, nullptr); + std::unique_ptr<wallet2> wal; + wal = std::move(rc.first); + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to create wallet"; + return false; + } + + cryptonote::address_parse_info info; + if(!get_account_address_from_str(info, wal->nettype(), req.address)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse public address"; + return false; + } + + epee::wipeable_string password = rc.second.password(); + epee::wipeable_string viewkey_string = req.viewkey; + crypto::secret_key viewkey; + if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse view key secret key"; + return false; + } + + try + { + if (!req.spendkey.empty()) + { + epee::wipeable_string spendkey_string = req.spendkey; + crypto::secret_key spendkey; + if (!spendkey_string.hex_to_pod(unwrap(unwrap(spendkey)))) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse spend key secret key"; + return false; + } + wal->generate(wallet_file, std::move(rc.second).password(), info.address, spendkey, viewkey, false); + res.info = "Wallet has been generated successfully."; + } + else + { + wal->generate(wallet_file, std::move(rc.second).password(), info.address, viewkey, false); + res.info = "Watch-only wallet has been generated successfully."; + } + MINFO("Wallet has been generated.\n"); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to generate wallet"; + return false; + } + + // set blockheight if given + try + { + wal->set_refresh_from_block_height(req.restore_height); + wal->rewrite(wallet_file, password); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + if (m_wallet) + { + try + { + m_wallet->store(); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + delete m_wallet; + } + m_wallet = wal.release(); + res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request &req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response &res, epee::json_rpc::error &er, const connection_context *ctx) { if (m_wallet_dir.empty()) @@ -3741,6 +3957,57 @@ namespace tools return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_validate_address(const wallet_rpc::COMMAND_RPC_VALIDATE_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_VALIDATE_ADDRESS::response& res, epee::json_rpc::error& er, const connection_context *ctx) + { + cryptonote::address_parse_info info; + static const struct { cryptonote::network_type type; const char *stype; } net_types[] = { + { cryptonote::MAINNET, "mainnet" }, + { cryptonote::TESTNET, "testnet" }, + { cryptonote::STAGENET, "stagenet" }, + }; + for (const auto &net_type: net_types) + { + if (!req.any_net_type && net_type.type != m_wallet->nettype()) + continue; + if (req.allow_openalias) + { + std::string address; + res.valid = get_account_address_from_str_or_url(info, net_type.type, req.address, + [&er, &address](const std::string &url, const std::vector<std::string> &addresses, bool dnssec_valid)->std::string { + if (!dnssec_valid) + { + er.message = std::string("Invalid DNSSEC for ") + url; + return {}; + } + if (addresses.empty()) + { + er.message = std::string("No Monero address found at ") + url; + return {}; + } + address = addresses[0]; + return address; + }); + if (res.valid) + res.openalias_address = address; + } + else + { + res.valid = cryptonote::get_account_address_from_str(info, net_type.type, req.address); + } + if (res.valid) + { + res.integrated = info.has_payment_id; + res.subaddress = info.is_subaddress; + res.nettype = net_type.stype; + return true; + } + } + + er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; + er.message = std::string("Invalid address"); + return false; + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_get_version(const wallet_rpc::COMMAND_RPC_GET_VERSION::request& req, wallet_rpc::COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& er, const connection_context *ctx) { res.version = WALLET_RPC_VERSION; @@ -3937,6 +4204,11 @@ int main(int argc, char** argv) { command_line::add_arg(desc_params, arg_from_json); command_line::add_arg(desc_params, arg_wallet_dir); command_line::add_arg(desc_params, arg_prompt_for_password); + command_line::add_arg(desc_params, arg_rpc_ssl); + command_line::add_arg(desc_params, arg_rpc_ssl_private_key); + command_line::add_arg(desc_params, arg_rpc_ssl_certificate); + command_line::add_arg(desc_params, arg_rpc_ssl_allowed_certificates); + command_line::add_arg(desc_params, arg_rpc_ssl_allowed_fingerprints); daemonizer::init_options(hidden_options, desc_params); desc_params.add(hidden_options); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 1a54e4c79..affaf10f7 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -137,6 +137,7 @@ namespace tools MAP_JON_RPC_WE("open_wallet", on_open_wallet, wallet_rpc::COMMAND_RPC_OPEN_WALLET) MAP_JON_RPC_WE("close_wallet", on_close_wallet, wallet_rpc::COMMAND_RPC_CLOSE_WALLET) MAP_JON_RPC_WE("change_wallet_password", on_change_wallet_password, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD) + MAP_JON_RPC_WE("generate_from_keys", on_generate_from_keys, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS) MAP_JON_RPC_WE("restore_deterministic_wallet", on_restore_deterministic_wallet, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET) MAP_JON_RPC_WE("is_multisig", on_is_multisig, wallet_rpc::COMMAND_RPC_IS_MULTISIG) MAP_JON_RPC_WE("prepare_multisig", on_prepare_multisig, wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG) @@ -147,6 +148,7 @@ namespace tools MAP_JON_RPC_WE("exchange_multisig_keys", on_exchange_multisig_keys, wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS) MAP_JON_RPC_WE("sign_multisig", on_sign_multisig, wallet_rpc::COMMAND_RPC_SIGN_MULTISIG) MAP_JON_RPC_WE("submit_multisig", on_submit_multisig, wallet_rpc::COMMAND_RPC_SUBMIT_MULTISIG) + MAP_JON_RPC_WE("validate_address", on_validate_address, wallet_rpc::COMMAND_RPC_VALIDATE_ADDRESS) MAP_JON_RPC_WE("get_version", on_get_version, wallet_rpc::COMMAND_RPC_GET_VERSION) END_JSON_RPC_MAP() END_URI_MAP2() @@ -216,6 +218,7 @@ namespace tools bool on_open_wallet(const wallet_rpc::COMMAND_RPC_OPEN_WALLET::request& req, wallet_rpc::COMMAND_RPC_OPEN_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_close_wallet(const wallet_rpc::COMMAND_RPC_CLOSE_WALLET::request& req, wallet_rpc::COMMAND_RPC_CLOSE_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_change_wallet_password(const wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::request& req, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); + bool on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request& req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_prepare_multisig(const wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); @@ -226,6 +229,7 @@ namespace tools bool on_exchange_multisig_keys(const wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS::request& req, wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_sign_multisig(const wallet_rpc::COMMAND_RPC_SIGN_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_SIGN_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_submit_multisig(const wallet_rpc::COMMAND_RPC_SUBMIT_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_SUBMIT_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); + bool on_validate_address(const wallet_rpc::COMMAND_RPC_VALIDATE_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_VALIDATE_ADDRESS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_get_version(const wallet_rpc::COMMAND_RPC_GET_VERSION::request& req, wallet_rpc::COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); //json rpc v2 diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index f0c1a4e9d..0879502b9 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 7 +#define WALLET_RPC_VERSION_MINOR 8 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -59,18 +59,22 @@ namespace wallet_rpc struct COMMAND_RPC_GET_BALANCE { - struct request + struct request_t { uint32_t account_index; std::set<uint32_t> address_indices; + bool all_accounts; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(account_index) KV_SERIALIZE(address_indices) + KV_SERIALIZE_OPT(all_accounts, false); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct per_subaddress_info { + uint32_t account_index; uint32_t address_index; std::string address; uint64_t balance; @@ -79,6 +83,7 @@ namespace wallet_rpc uint64_t num_unspent_outputs; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(account_index) KV_SERIALIZE(address_index) KV_SERIALIZE(address) KV_SERIALIZE(balance) @@ -88,7 +93,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { uint64_t balance; uint64_t unlocked_balance; @@ -102,11 +107,12 @@ namespace wallet_rpc KV_SERIALIZE(per_subaddress) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_ADDRESS { - struct request + struct request_t { uint32_t account_index; std::vector<uint32_t> address_index; @@ -115,6 +121,7 @@ namespace wallet_rpc KV_SERIALIZE(address_index) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct address_info { @@ -131,7 +138,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { std::string address; // to remain compatible with older RPC format std::vector<address_info> addresses; @@ -141,30 +148,33 @@ namespace wallet_rpc KV_SERIALIZE(addresses) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_ADDRESS_INDEX { - struct request + struct request_t { std::string address; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(address) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { cryptonote::subaddress_index index; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(index) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CREATE_ADDRESS { - struct request + struct request_t { uint32_t account_index; std::string label; @@ -174,8 +184,9 @@ namespace wallet_rpc KV_SERIALIZE(label) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string address; uint32_t address_index; @@ -185,11 +196,12 @@ namespace wallet_rpc KV_SERIALIZE(address_index) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_LABEL_ADDRESS { - struct request + struct request_t { cryptonote::subaddress_index index; std::string label; @@ -199,17 +211,19 @@ namespace wallet_rpc KV_SERIALIZE(label) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_ACCOUNTS { - struct request + struct request_t { std::string tag; // all accounts if empty, otherwise those accounts with this tag @@ -217,6 +231,7 @@ namespace wallet_rpc KV_SERIALIZE(tag) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct subaddress_account_info { @@ -237,7 +252,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { uint64_t total_balance; uint64_t total_unlocked_balance; @@ -249,19 +264,21 @@ namespace wallet_rpc KV_SERIALIZE(subaddress_accounts) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CREATE_ACCOUNT { - struct request + struct request_t { std::string label; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(label) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint32_t account_index; std::string address; // the 0-th address for convenience @@ -270,11 +287,12 @@ namespace wallet_rpc KV_SERIALIZE(address) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_LABEL_ACCOUNT { - struct request + struct request_t { uint32_t account_index; std::string label; @@ -284,21 +302,24 @@ namespace wallet_rpc KV_SERIALIZE(label) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_ACCOUNT_TAGS { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct account_tag_info { @@ -313,7 +334,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { std::vector<account_tag_info> account_tags; @@ -321,11 +342,12 @@ namespace wallet_rpc KV_SERIALIZE(account_tags) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_TAG_ACCOUNTS { - struct request + struct request_t { std::string tag; std::set<uint32_t> accounts; @@ -335,17 +357,19 @@ namespace wallet_rpc KV_SERIALIZE(accounts) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_UNTAG_ACCOUNTS { - struct request + struct request_t { std::set<uint32_t> accounts; @@ -353,17 +377,19 @@ namespace wallet_rpc KV_SERIALIZE(accounts) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION { - struct request + struct request_t { std::string tag; std::string description; @@ -373,29 +399,33 @@ namespace wallet_rpc KV_SERIALIZE(description) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_HEIGHT { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint64_t height; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(height) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct transfer_destination @@ -410,7 +440,7 @@ namespace wallet_rpc struct COMMAND_RPC_TRANSFER { - struct request + struct request_t { std::list<transfer_destination> destinations; uint32_t account_index; @@ -440,8 +470,9 @@ namespace wallet_rpc KV_SERIALIZE_OPT(get_tx_metadata, false) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string tx_hash; std::string tx_key; @@ -463,11 +494,12 @@ namespace wallet_rpc KV_SERIALIZE(unsigned_txset) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_TRANSFER_SPLIT { - struct request + struct request_t { std::list<transfer_destination> destinations; uint32_t account_index; @@ -497,6 +529,7 @@ namespace wallet_rpc KV_SERIALIZE_OPT(get_tx_metadata, false) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct key_list { @@ -507,7 +540,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { std::list<std::string> tx_hash_list; std::list<std::string> tx_key_list; @@ -529,6 +562,7 @@ namespace wallet_rpc KV_SERIALIZE(unsigned_txset) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_DESCRIBE_TRANSFER @@ -573,7 +607,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct request + struct request_t { std::string unsigned_txset; @@ -581,8 +615,9 @@ namespace wallet_rpc KV_SERIALIZE(unsigned_txset) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<transfer_description> desc; @@ -590,11 +625,12 @@ namespace wallet_rpc KV_SERIALIZE(desc) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SIGN_TRANSFER { - struct request + struct request_t { std::string unsigned_txset; bool export_raw; @@ -606,8 +642,9 @@ namespace wallet_rpc KV_SERIALIZE_OPT(get_tx_keys, false) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string signed_txset; std::list<std::string> tx_hash_list; @@ -621,11 +658,12 @@ namespace wallet_rpc KV_SERIALIZE(tx_key_list) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SUBMIT_TRANSFER { - struct request + struct request_t { std::string tx_data_hex; @@ -633,8 +671,9 @@ namespace wallet_rpc KV_SERIALIZE(tx_data_hex) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<std::string> tx_hash_list; @@ -642,11 +681,12 @@ namespace wallet_rpc KV_SERIALIZE(tx_hash_list) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SWEEP_DUST { - struct request + struct request_t { bool get_tx_keys; bool do_not_relay; @@ -660,6 +700,7 @@ namespace wallet_rpc KV_SERIALIZE_OPT(get_tx_metadata, false) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct key_list { @@ -670,7 +711,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { std::list<std::string> tx_hash_list; std::list<std::string> tx_key_list; @@ -692,11 +733,12 @@ namespace wallet_rpc KV_SERIALIZE(unsigned_txset) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SWEEP_ALL { - struct request + struct request_t { std::string address; uint32_t account_index; @@ -730,6 +772,7 @@ namespace wallet_rpc KV_SERIALIZE_OPT(get_tx_metadata, false) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct key_list { @@ -740,7 +783,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { std::list<std::string> tx_hash_list; std::list<std::string> tx_key_list; @@ -762,11 +805,12 @@ namespace wallet_rpc KV_SERIALIZE(unsigned_txset) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SWEEP_SINGLE { - struct request + struct request_t { std::string address; uint32_t priority; @@ -796,8 +840,9 @@ namespace wallet_rpc KV_SERIALIZE_OPT(get_tx_metadata, false) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string tx_hash; std::string tx_key; @@ -819,11 +864,12 @@ namespace wallet_rpc KV_SERIALIZE(unsigned_txset) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_RELAY_TX { - struct request + struct request_t { std::string hex; @@ -831,8 +877,9 @@ namespace wallet_rpc KV_SERIALIZE(hex) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string tx_hash; @@ -840,21 +887,24 @@ namespace wallet_rpc KV_SERIALIZE(tx_hash) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_STORE { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct payment_details @@ -880,7 +930,7 @@ namespace wallet_rpc struct COMMAND_RPC_GET_PAYMENTS { - struct request + struct request_t { std::string payment_id; @@ -888,8 +938,9 @@ namespace wallet_rpc KV_SERIALIZE(payment_id) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<payment_details> payments; @@ -897,11 +948,12 @@ namespace wallet_rpc KV_SERIALIZE(payments) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_BULK_PAYMENTS { - struct request + struct request_t { std::vector<std::string> payment_ids; uint64_t min_block_height; @@ -911,8 +963,9 @@ namespace wallet_rpc KV_SERIALIZE(min_block_height) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<payment_details> payments; @@ -920,6 +973,7 @@ namespace wallet_rpc KV_SERIALIZE(payments) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct transfer_details @@ -943,7 +997,7 @@ namespace wallet_rpc struct COMMAND_RPC_INCOMING_TRANSFERS { - struct request + struct request_t { std::string transfer_type; uint32_t account_index; @@ -955,8 +1009,9 @@ namespace wallet_rpc KV_SERIALIZE(subaddr_indices) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<transfer_details> transfers; @@ -964,12 +1019,13 @@ namespace wallet_rpc KV_SERIALIZE(transfers) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; //JSON RPC V2 struct COMMAND_RPC_QUERY_KEY { - struct request + struct request_t { std::string key_type; @@ -977,8 +1033,9 @@ namespace wallet_rpc KV_SERIALIZE(key_type) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string key; @@ -986,11 +1043,12 @@ namespace wallet_rpc KV_SERIALIZE(key) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_MAKE_INTEGRATED_ADDRESS { - struct request + struct request_t { std::string standard_address; std::string payment_id; @@ -1000,8 +1058,9 @@ namespace wallet_rpc KV_SERIALIZE(payment_id) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string integrated_address; std::string payment_id; @@ -1011,11 +1070,12 @@ namespace wallet_rpc KV_SERIALIZE(payment_id) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS { - struct request + struct request_t { std::string integrated_address; @@ -1023,8 +1083,9 @@ namespace wallet_rpc KV_SERIALIZE(integrated_address) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string standard_address; std::string payment_id; @@ -1036,26 +1097,29 @@ namespace wallet_rpc KV_SERIALIZE(is_subaddress) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_STOP_WALLET { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_RESCAN_BLOCKCHAIN { - struct request + struct request_t { bool hard; @@ -1063,17 +1127,19 @@ namespace wallet_rpc KV_SERIALIZE_OPT(hard, false); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SET_TX_NOTES { - struct request + struct request_t { std::list<std::string> txids; std::list<std::string> notes; @@ -1083,17 +1149,19 @@ namespace wallet_rpc KV_SERIALIZE(notes) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_TX_NOTES { - struct request + struct request_t { std::list<std::string> txids; @@ -1101,8 +1169,9 @@ namespace wallet_rpc KV_SERIALIZE(txids) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<std::string> notes; @@ -1110,11 +1179,12 @@ namespace wallet_rpc KV_SERIALIZE(notes) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SET_ATTRIBUTE { - struct request + struct request_t { std::string key; std::string value; @@ -1124,17 +1194,19 @@ namespace wallet_rpc KV_SERIALIZE(value) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_ATTRIBUTE { - struct request + struct request_t { std::string key; @@ -1143,8 +1215,9 @@ namespace wallet_rpc KV_SERIALIZE(key) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string value; @@ -1152,11 +1225,12 @@ namespace wallet_rpc KV_SERIALIZE(value) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_TX_KEY { - struct request + struct request_t { std::string txid; @@ -1164,8 +1238,9 @@ namespace wallet_rpc KV_SERIALIZE(txid) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string tx_key; @@ -1173,11 +1248,12 @@ namespace wallet_rpc KV_SERIALIZE(tx_key) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CHECK_TX_KEY { - struct request + struct request_t { std::string txid; std::string tx_key; @@ -1189,8 +1265,9 @@ namespace wallet_rpc KV_SERIALIZE(address) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint64_t received; bool in_pool; @@ -1202,11 +1279,12 @@ namespace wallet_rpc KV_SERIALIZE(confirmations) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_TX_PROOF { - struct request + struct request_t { std::string txid; std::string address; @@ -1218,8 +1296,9 @@ namespace wallet_rpc KV_SERIALIZE(message) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string signature; @@ -1227,11 +1306,12 @@ namespace wallet_rpc KV_SERIALIZE(signature) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CHECK_TX_PROOF { - struct request + struct request_t { std::string txid; std::string address; @@ -1245,8 +1325,9 @@ namespace wallet_rpc KV_SERIALIZE(signature) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { bool good; uint64_t received; @@ -1260,6 +1341,7 @@ namespace wallet_rpc KV_SERIALIZE(confirmations) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct transfer_entry @@ -1301,7 +1383,7 @@ namespace wallet_rpc struct COMMAND_RPC_GET_SPEND_PROOF { - struct request + struct request_t { std::string txid; std::string message; @@ -1311,8 +1393,9 @@ namespace wallet_rpc KV_SERIALIZE(message) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string signature; @@ -1320,11 +1403,12 @@ namespace wallet_rpc KV_SERIALIZE(signature) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CHECK_SPEND_PROOF { - struct request + struct request_t { std::string txid; std::string message; @@ -1336,8 +1420,9 @@ namespace wallet_rpc KV_SERIALIZE(signature) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { bool good; @@ -1345,11 +1430,12 @@ namespace wallet_rpc KV_SERIALIZE(good) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_RESERVE_PROOF { - struct request + struct request_t { bool all; uint32_t account_index; // ignored when `all` is true @@ -1363,8 +1449,9 @@ namespace wallet_rpc KV_SERIALIZE(message) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string signature; @@ -1372,11 +1459,12 @@ namespace wallet_rpc KV_SERIALIZE(signature) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CHECK_RESERVE_PROOF { - struct request + struct request_t { std::string address; std::string message; @@ -1388,8 +1476,9 @@ namespace wallet_rpc KV_SERIALIZE(signature) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { bool good; uint64_t total; @@ -1401,11 +1490,12 @@ namespace wallet_rpc KV_SERIALIZE(spent) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_TRANSFERS { - struct request + struct request_t { bool in; bool out; @@ -1418,6 +1508,7 @@ namespace wallet_rpc uint64_t max_height; uint32_t account_index; std::set<uint32_t> subaddr_indices; + bool all_accounts; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(in); @@ -1430,10 +1521,12 @@ namespace wallet_rpc KV_SERIALIZE_OPT(max_height, (uint64_t)CRYPTONOTE_MAX_BLOCK_NUMBER); KV_SERIALIZE(account_index); KV_SERIALIZE(subaddr_indices); + KV_SERIALIZE_OPT(all_accounts, false); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<transfer_entry> in; std::list<transfer_entry> out; @@ -1449,11 +1542,12 @@ namespace wallet_rpc KV_SERIALIZE(pool); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_TRANSFER_BY_TXID { - struct request + struct request_t { std::string txid; uint32_t account_index; @@ -1463,8 +1557,9 @@ namespace wallet_rpc KV_SERIALIZE_OPT(account_index, (uint32_t)0) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { transfer_entry transfer; std::list<transfer_entry> transfers; @@ -1474,11 +1569,12 @@ namespace wallet_rpc KV_SERIALIZE(transfers); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SIGN { - struct request + struct request_t { std::string data; @@ -1486,8 +1582,9 @@ namespace wallet_rpc KV_SERIALIZE(data); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string signature; @@ -1495,11 +1592,12 @@ namespace wallet_rpc KV_SERIALIZE(signature); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_VERIFY { - struct request + struct request_t { std::string data; std::string address; @@ -1511,8 +1609,9 @@ namespace wallet_rpc KV_SERIALIZE(signature); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { bool good; @@ -1520,17 +1619,19 @@ namespace wallet_rpc KV_SERIALIZE(good); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_EXPORT_OUTPUTS { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string outputs_data_hex; @@ -1538,11 +1639,12 @@ namespace wallet_rpc KV_SERIALIZE(outputs_data_hex); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_IMPORT_OUTPUTS { - struct request + struct request_t { std::string outputs_data_hex; @@ -1550,8 +1652,9 @@ namespace wallet_rpc KV_SERIALIZE(outputs_data_hex); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint64_t num_imported; @@ -1559,11 +1662,12 @@ namespace wallet_rpc KV_SERIALIZE(num_imported); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_EXPORT_KEY_IMAGES { - struct request + struct request_t { bool all; @@ -1571,6 +1675,7 @@ namespace wallet_rpc KV_SERIALIZE_OPT(all, false); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct signed_key_image { @@ -1583,7 +1688,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { uint32_t offset; std::vector<signed_key_image> signed_key_images; @@ -1593,6 +1698,7 @@ namespace wallet_rpc KV_SERIALIZE(signed_key_images); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_IMPORT_KEY_IMAGES @@ -1608,7 +1714,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct request + struct request_t { uint32_t offset; std::vector<signed_key_image> signed_key_images; @@ -1618,8 +1724,9 @@ namespace wallet_rpc KV_SERIALIZE(signed_key_images); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint64_t height; uint64_t spent; @@ -1631,6 +1738,7 @@ namespace wallet_rpc KV_SERIALIZE(unspent) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct uri_spec @@ -1652,11 +1760,12 @@ namespace wallet_rpc struct COMMAND_RPC_MAKE_URI { - struct request: public uri_spec + struct request_t: public uri_spec { }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string uri; @@ -1664,11 +1773,12 @@ namespace wallet_rpc KV_SERIALIZE(uri) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_PARSE_URI { - struct request + struct request_t { std::string uri; @@ -1676,8 +1786,9 @@ namespace wallet_rpc KV_SERIALIZE(uri) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uri_spec uri; std::vector<std::string> unknown_parameters; @@ -1687,11 +1798,12 @@ namespace wallet_rpc KV_SERIALIZE(unknown_parameters); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_ADD_ADDRESS_BOOK_ENTRY { - struct request + struct request_t { std::string address; std::string payment_id; @@ -1703,8 +1815,9 @@ namespace wallet_rpc KV_SERIALIZE(description) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint64_t index; @@ -1712,11 +1825,12 @@ namespace wallet_rpc KV_SERIALIZE(index); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY { - struct request + struct request_t { std::list<uint64_t> entries; @@ -1724,6 +1838,7 @@ namespace wallet_rpc KV_SERIALIZE(entries) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; struct entry { @@ -1740,7 +1855,7 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; - struct response + struct response_t { std::vector<entry> entries; @@ -1748,11 +1863,12 @@ namespace wallet_rpc KV_SERIALIZE(entries) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_DELETE_ADDRESS_BOOK_ENTRY { - struct request + struct request_t { uint64_t index; @@ -1760,32 +1876,36 @@ namespace wallet_rpc KV_SERIALIZE(index); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_RESCAN_SPENT { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_REFRESH { - struct request + struct request_t { uint64_t start_height; @@ -1793,8 +1913,9 @@ namespace wallet_rpc KV_SERIALIZE_OPT(start_height, (uint64_t) 0) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint64_t blocks_fetched; bool received_money; @@ -1804,11 +1925,12 @@ namespace wallet_rpc KV_SERIALIZE(received_money); END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_START_MINING { - struct request + struct request_t { uint64_t threads_count; bool do_background_mining; @@ -1820,37 +1942,43 @@ namespace wallet_rpc KV_SERIALIZE(ignore_battery) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_STOP_MINING { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_LANGUAGES { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; - struct response + typedef epee::misc_utils::struct_init<request_t> request; + + struct response_t { std::vector<std::string> languages; @@ -1858,11 +1986,12 @@ namespace wallet_rpc KV_SERIALIZE(languages) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CREATE_WALLET { - struct request + struct request_t { std::string filename; std::string password; @@ -1874,16 +2003,19 @@ namespace wallet_rpc KV_SERIALIZE(language) END_KV_SERIALIZE_MAP() }; - struct response + typedef epee::misc_utils::struct_init<request_t> request; + + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_OPEN_WALLET { - struct request + struct request_t { std::string filename; std::string password; @@ -1893,31 +2025,36 @@ namespace wallet_rpc KV_SERIALIZE(password) END_KV_SERIALIZE_MAP() }; - struct response + typedef epee::misc_utils::struct_init<request_t> request; + + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CLOSE_WALLET { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_CHANGE_WALLET_PASSWORD { - struct request + struct request_t { std::string old_password; std::string new_password; @@ -1927,16 +2064,52 @@ namespace wallet_rpc KV_SERIALIZE(new_password) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; + + struct response_t + { + BEGIN_KV_SERIALIZE_MAP() + END_KV_SERIALIZE_MAP() + }; + typedef epee::misc_utils::struct_init<response_t> response; + }; + + struct COMMAND_RPC_GENERATE_FROM_KEYS + { + struct request + { + uint64_t restore_height; + std::string filename; + std::string address; + std::string spendkey; + std::string viewkey; + std::string password; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(restore_height, (uint64_t)0) + KV_SERIALIZE(filename) + KV_SERIALIZE(address) + KV_SERIALIZE(spendkey) + KV_SERIALIZE(viewkey) + KV_SERIALIZE(password) + END_KV_SERIALIZE_MAP() + }; + struct response { + std::string address; + std::string info; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(address) + KV_SERIALIZE(info) END_KV_SERIALIZE_MAP() }; }; struct COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET { - struct request + struct request_t { uint64_t restore_height; std::string filename; @@ -1954,8 +2127,9 @@ namespace wallet_rpc KV_SERIALIZE(language) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string address; std::string seed; @@ -1969,17 +2143,19 @@ namespace wallet_rpc KV_SERIALIZE(was_deprecated) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_IS_MULTISIG { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { bool multisig; bool ready; @@ -1993,17 +2169,19 @@ namespace wallet_rpc KV_SERIALIZE(total) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_PREPARE_MULTISIG { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string multisig_info; @@ -2011,11 +2189,12 @@ namespace wallet_rpc KV_SERIALIZE(multisig_info) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_MAKE_MULTISIG { - struct request + struct request_t { std::vector<std::string> multisig_info; uint32_t threshold; @@ -2027,8 +2206,9 @@ namespace wallet_rpc KV_SERIALIZE(password) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string address; std::string multisig_info; @@ -2038,17 +2218,19 @@ namespace wallet_rpc KV_SERIALIZE(multisig_info) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_EXPORT_MULTISIG { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string info; @@ -2056,11 +2238,12 @@ namespace wallet_rpc KV_SERIALIZE(info) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_IMPORT_MULTISIG { - struct request + struct request_t { std::vector<std::string> info; @@ -2068,8 +2251,9 @@ namespace wallet_rpc KV_SERIALIZE(info) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint64_t n_outputs; @@ -2077,11 +2261,12 @@ namespace wallet_rpc KV_SERIALIZE(n_outputs) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_FINALIZE_MULTISIG { - struct request + struct request_t { std::string password; std::vector<std::string> multisig_info; @@ -2091,8 +2276,9 @@ namespace wallet_rpc KV_SERIALIZE(multisig_info) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string address; @@ -2100,11 +2286,12 @@ namespace wallet_rpc KV_SERIALIZE(address) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_EXCHANGE_MULTISIG_KEYS { - struct request + struct request_t { std::string password; std::vector<std::string> multisig_info; @@ -2114,8 +2301,9 @@ namespace wallet_rpc KV_SERIALIZE(multisig_info) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string address; std::string multisig_info; @@ -2125,11 +2313,12 @@ namespace wallet_rpc KV_SERIALIZE(multisig_info) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SIGN_MULTISIG { - struct request + struct request_t { std::string tx_data_hex; @@ -2137,8 +2326,9 @@ namespace wallet_rpc KV_SERIALIZE(tx_data_hex) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::string tx_data_hex; std::list<std::string> tx_hash_list; @@ -2148,11 +2338,12 @@ namespace wallet_rpc KV_SERIALIZE(tx_hash_list) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_SUBMIT_MULTISIG { - struct request + struct request_t { std::string tx_data_hex; @@ -2160,8 +2351,9 @@ namespace wallet_rpc KV_SERIALIZE(tx_data_hex) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { std::list<std::string> tx_hash_list; @@ -2169,17 +2361,19 @@ namespace wallet_rpc KV_SERIALIZE(tx_hash_list) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; }; struct COMMAND_RPC_GET_VERSION { - struct request + struct request_t { BEGIN_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<request_t> request; - struct response + struct response_t { uint32_t version; @@ -2187,6 +2381,42 @@ namespace wallet_rpc KV_SERIALIZE(version) END_KV_SERIALIZE_MAP() }; + typedef epee::misc_utils::struct_init<response_t> response; + }; + + struct COMMAND_RPC_VALIDATE_ADDRESS + { + struct request_t + { + std::string address; + bool any_net_type; + bool allow_openalias; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(address) + KV_SERIALIZE_OPT(any_net_type, false) + KV_SERIALIZE_OPT(allow_openalias, false) + END_KV_SERIALIZE_MAP() + }; + typedef epee::misc_utils::struct_init<request_t> request; + + struct response_t + { + bool valid; + bool integrated; + bool subaddress; + std::string nettype; + std::string openalias_address; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(valid) + KV_SERIALIZE(integrated) + KV_SERIALIZE(subaddress) + KV_SERIALIZE(nettype) + KV_SERIALIZE(openalias_address) + END_KV_SERIALIZE_MAP() + }; + typedef epee::misc_utils::struct_init<response_t> response; }; } diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h index 9b3a2847d..440a58a47 100644 --- a/src/wallet/wallet_rpc_server_error_codes.h +++ b/src/wallet/wallet_rpc_server_error_codes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // |