mirror of
https://github.com/wownero/wownero-cpp.git
synced 2026-10-18 23:58:59 +02:00
Merge branch 'wallet_keys_5_rm_mm'
This commit is contained in:
+2
-1
@@ -238,7 +238,8 @@ set(
|
||||
src/daemon/monero_daemon_model.cpp
|
||||
src/daemon/monero_daemon.cpp
|
||||
src/wallet/monero_wallet_model.cpp
|
||||
src/wallet/monero_wallet.cpp
|
||||
src/wallet/monero_wallet_keys.cpp
|
||||
src/wallet/monero_wallet_core.cpp
|
||||
)
|
||||
|
||||
add_library(monero-cpp SHARED ${LIBRARY_SRC_FILES})
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef crypto_verify_16_H
|
||||
#define crypto_verify_16_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define crypto_verify_16_BYTES 16U
|
||||
SODIUM_EXPORT
|
||||
size_t crypto_verify_16_bytes(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int crypto_verify_16(const unsigned char *x, const unsigned char *y)
|
||||
__attribute__ ((warn_unused_result));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef crypto_verify_32_H
|
||||
#define crypto_verify_32_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define crypto_verify_32_BYTES 32U
|
||||
SODIUM_EXPORT
|
||||
size_t crypto_verify_32_bytes(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int crypto_verify_32(const unsigned char *x, const unsigned char *y)
|
||||
__attribute__ ((warn_unused_result));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef crypto_verify_64_H
|
||||
#define crypto_verify_64_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define crypto_verify_64_BYTES 64U
|
||||
SODIUM_EXPORT
|
||||
size_t crypto_verify_64_bytes(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int crypto_verify_64(const unsigned char *x, const unsigned char *y)
|
||||
__attribute__ ((warn_unused_result));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crypto_verify_16.h"
|
||||
#include "crypto_verify_32.h"
|
||||
#include "crypto_verify_64.h"
|
||||
|
||||
size_t
|
||||
crypto_verify_16_bytes(void)
|
||||
{
|
||||
return crypto_verify_16_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_verify_32_bytes(void)
|
||||
{
|
||||
return crypto_verify_32_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_verify_64_bytes(void)
|
||||
{
|
||||
return crypto_verify_64_BYTES;
|
||||
}
|
||||
|
||||
#if defined(HAVE_EMMINTRIN_H) && defined(__SSE2__)
|
||||
|
||||
# ifdef __GNUC__
|
||||
# pragma GCC target("sse2")
|
||||
# endif
|
||||
# include <emmintrin.h>
|
||||
|
||||
static inline int
|
||||
crypto_verify_n(const unsigned char *x_, const unsigned char *y_,
|
||||
const int n)
|
||||
{
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
volatile __m128i v1, v2, z;
|
||||
volatile int m;
|
||||
int i;
|
||||
|
||||
const volatile __m128i *volatile x =
|
||||
(const volatile __m128i *volatile) (const void *) x_;
|
||||
const volatile __m128i *volatile y =
|
||||
(const volatile __m128i *volatile) (const void *) y_;
|
||||
v1 = _mm_loadu_si128((const __m128i *) &x[0]);
|
||||
v2 = _mm_loadu_si128((const __m128i *) &y[0]);
|
||||
z = _mm_xor_si128(v1, v2);
|
||||
for (i = 1; i < n / 16; i++) {
|
||||
v1 = _mm_loadu_si128((const __m128i *) &x[i]);
|
||||
v2 = _mm_loadu_si128((const __m128i *) &y[i]);
|
||||
z = _mm_or_si128(z, _mm_xor_si128(v1, v2));
|
||||
}
|
||||
m = _mm_movemask_epi8(_mm_cmpeq_epi32(z, zero));
|
||||
v1 = zero; v2 = zero; z = zero;
|
||||
|
||||
return (int) (((uint32_t) m + 1U) >> 16) - 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int
|
||||
crypto_verify_n(const unsigned char *x_, const unsigned char *y_,
|
||||
const int n)
|
||||
{
|
||||
const volatile unsigned char *volatile x =
|
||||
(const volatile unsigned char *volatile) x_;
|
||||
const volatile unsigned char *volatile y =
|
||||
(const volatile unsigned char *volatile) y_;
|
||||
volatile uint_fast16_t d = 0U;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
d |= x[i] ^ y[i];
|
||||
}
|
||||
return (1 & ((d - 1) >> 8)) - 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
crypto_verify_16(const unsigned char *x, const unsigned char *y)
|
||||
{
|
||||
return crypto_verify_n(x, y, crypto_verify_16_BYTES);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_verify_32(const unsigned char *x, const unsigned char *y)
|
||||
{
|
||||
return crypto_verify_n(x, y, crypto_verify_32_BYTES);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_verify_64(const unsigned char *x, const unsigned char *y)
|
||||
{
|
||||
return crypto_verify_n(x, y, crypto_verify_64_BYTES);
|
||||
}
|
||||
+366
-219
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2019 woodser
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Parts of this file are originally copyright (c) 2014-2019, The Monero Project
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "monero_wallet.h"
|
||||
#include "wallet/wallet2.h"
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace crypto;
|
||||
using namespace monero;
|
||||
|
||||
/**
|
||||
* Public library interface.
|
||||
*/
|
||||
namespace monero {
|
||||
|
||||
// --------------------------------- LISTENERS ------------------------------
|
||||
|
||||
// forward declaration of internal wallet2 listener
|
||||
struct wallet2_listener;
|
||||
|
||||
// ---------------------------- WALLET INTERFACE ----------------------------
|
||||
|
||||
/**
|
||||
* Monero wallet implmentation which uses monero-project's wallet2.
|
||||
*/
|
||||
class monero_wallet_core : public monero_wallet {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Indicates if a wallet exists at the given path.
|
||||
*
|
||||
* @param path is the path to check for a wallet
|
||||
* @return true if a wallet exists at the given path, false otherwise
|
||||
*/
|
||||
static bool wallet_exists(const string& path);
|
||||
|
||||
/**
|
||||
* Open an existing wallet.
|
||||
*
|
||||
* @param path is the path to the wallet file to open
|
||||
* @param password is the password of the wallet file to open
|
||||
* @param network_type is the wallet's network type
|
||||
*/
|
||||
static monero_wallet_core* open_wallet(const string& path, const string& password, const monero_network_type network_type);
|
||||
|
||||
/**
|
||||
* Create a new wallet with a randomly generated seed.
|
||||
*
|
||||
* @param path is the path to create the wallet
|
||||
* @param password is the password encrypt the wallet
|
||||
* @param network_type is the wallet's network type
|
||||
* @param daemon_connection is connection information to a daemon (default = an unconnected wallet)
|
||||
* @param language is the wallet and mnemonic's language (default = "English")
|
||||
*/
|
||||
static monero_wallet_core* create_wallet_random(const string& path, const string& password, const monero_network_type network_type, const monero_rpc_connection& daemon_connection, const string& language = "English");
|
||||
|
||||
/**
|
||||
* Create a wallet from an existing mnemonic phrase.
|
||||
*
|
||||
* @param path is the path to create the wallet
|
||||
* @param password is the password encrypt the wallet
|
||||
* @param network_type is the wallet's network type
|
||||
* @param mnemonic is the mnemonic of the wallet to construct
|
||||
* @param daemon_connection is connection information to a daemon (default = an unconnected wallet)
|
||||
* @param restore_height is the block height to restore (i.e. scan the chain) from (default = 0)
|
||||
*/
|
||||
static monero_wallet_core* create_wallet_from_mnemonic(const string& path, const string& password, const monero_network_type network_type, const string& mnemonic);
|
||||
static monero_wallet_core* create_wallet_from_mnemonic(const string& path, const string& password, const monero_network_type network_type, const string& mnemonic, const monero_rpc_connection& daemon_connection, uint64_t restore_height);
|
||||
|
||||
/**
|
||||
* Create a wallet from an address, view key, and spend key.
|
||||
*
|
||||
* @param path is the path to create the wallet
|
||||
* @param password is the password encrypt the wallet
|
||||
* @param network_type is the wallet's network type
|
||||
* @param address is the address of the wallet to construct
|
||||
* @param view_key is the private view key of the wallet to construct
|
||||
* @param spend_key is the private spend key of the wallet to construct
|
||||
* @param daemon_connection is connection information to a daemon (default = an unconnected wallet)
|
||||
* @param restore_height is the block height to restore (i.e. scan the chain) from (default = 0)
|
||||
* @param language is the wallet and mnemonic's language (default = "English")
|
||||
*/
|
||||
static monero_wallet_core* create_wallet_from_keys(const string& path, const string& password, const monero_network_type network_type, const string& address, const string& view_key, const string& spend_key);
|
||||
static monero_wallet_core* create_wallet_from_keys(const string& path, const string& password, const monero_network_type network_type, const string& address, const string& view_key, const string& spend_key, const monero_rpc_connection& daemon_connection, uint64_t restore_height);
|
||||
static monero_wallet_core* create_wallet_from_keys(const string& path, const string& password, const monero_network_type network_type, const string& address, const string& view_key, const string& spend_key, const monero_rpc_connection& daemon_connection, uint64_t restore_height, const string& language);
|
||||
|
||||
/**
|
||||
* Destruct the wallet.
|
||||
*/
|
||||
~monero_wallet_core();
|
||||
|
||||
/**
|
||||
* Supported wallet methods.
|
||||
*/
|
||||
void set_daemon_connection(const string& uri, const string& username = "", const string& password = "");
|
||||
void set_daemon_connection(const monero_rpc_connection& connection);
|
||||
shared_ptr<monero_rpc_connection> get_daemon_connection() const;
|
||||
bool is_connected() const;
|
||||
bool is_daemon_synced() const;
|
||||
bool is_daemon_trusted() const;
|
||||
bool is_synced() const;
|
||||
monero_version get_version() const;
|
||||
string get_path() const;
|
||||
monero_network_type get_network_type() const;
|
||||
string get_mnemonic() const;
|
||||
string get_language() const;
|
||||
vector<string> get_languages() const;
|
||||
string get_public_view_key() const;
|
||||
string get_private_view_key() const;
|
||||
string get_public_spend_key() const;
|
||||
string get_private_spend_key() const;
|
||||
string get_address(const uint32_t account_idx, const uint32_t subaddress_idx) const;
|
||||
monero_subaddress get_address_index(const string& address) const;
|
||||
monero_integrated_address get_integrated_address(const string& standard_address = "", const string& payment_id = "") const;
|
||||
monero_integrated_address decode_integrated_address(const string& integrated_address) const;
|
||||
uint64_t get_height() const;
|
||||
uint64_t get_restore_height() const;
|
||||
void set_restore_height(uint64_t restore_height);
|
||||
uint64_t get_daemon_height() const;
|
||||
uint64_t get_daemon_max_peer_height() const;
|
||||
void add_listener(monero_wallet_listener& listener);
|
||||
void remove_listener(monero_wallet_listener& listener);
|
||||
set<monero_wallet_listener*> get_listeners();
|
||||
monero_sync_result sync();
|
||||
monero_sync_result sync(monero_sync_listener& listener);
|
||||
monero_sync_result sync(uint64_t start_height);
|
||||
monero_sync_result sync(uint64_t start_height, monero_sync_listener& listener);
|
||||
void start_syncing();
|
||||
void stop_syncing();
|
||||
void rescan_spent();
|
||||
void rescan_blockchain();
|
||||
uint64_t get_balance() const;
|
||||
uint64_t get_balance(uint32_t account_idx) const;
|
||||
uint64_t get_balance(uint32_t account_idx, uint32_t subaddress_idx) const;
|
||||
uint64_t get_unlocked_balance() const;
|
||||
uint64_t get_unlocked_balance(uint32_t account_idx) const;
|
||||
uint64_t get_unlocked_balance(uint32_t account_idx, uint32_t subaddress_idx) const;
|
||||
vector<monero_account> get_accounts(bool include_subaddresses, const string& tag) const;
|
||||
monero_account get_account(const uint32_t account_idx, bool include_subaddresses) const;
|
||||
monero_account create_account(const string& label = "");
|
||||
vector<monero_subaddress> get_subaddresses(const uint32_t account_idx, const vector<uint32_t>& subaddress_indices) const;
|
||||
monero_subaddress create_subaddress(uint32_t account_idx, const string& label = "");
|
||||
vector<shared_ptr<monero_tx_wallet>> get_txs() const;
|
||||
vector<shared_ptr<monero_tx_wallet>> get_txs(const monero_tx_query& query) const;
|
||||
vector<shared_ptr<monero_transfer>> get_transfers(const monero_transfer_query& query) const;
|
||||
vector<shared_ptr<monero_output_wallet>> get_outputs(const monero_output_query& query) const;
|
||||
string get_outputs_hex() const;
|
||||
int import_outputs_hex(const string& outputs_hex);
|
||||
vector<shared_ptr<monero_key_image>> get_key_images() const;
|
||||
shared_ptr<monero_key_image_import_result> import_key_images(const vector<shared_ptr<monero_key_image>>& key_images);
|
||||
monero_tx_set create_tx(monero_send_request& request);
|
||||
monero_tx_set create_tx(uint32_t account_index, string address, uint64_t amount);
|
||||
monero_tx_set create_tx(int account_index, string address, uint64_t amount, monero_send_priority priority);
|
||||
monero_tx_set create_txs(monero_send_request& request);
|
||||
string relay_tx(const string& tx_metadata);
|
||||
string relay_tx(const monero_tx_wallet& tx);
|
||||
vector<string> relay_txs(const vector<string>& tx_metadatas);
|
||||
vector<string> relay_txs(const vector<shared_ptr<monero_tx_wallet>>& txs);
|
||||
monero_tx_set send(const monero_send_request& request);
|
||||
monero_tx_set send(uint32_t account_index, string address, uint64_t amount);
|
||||
monero_tx_set send(uint32_t account_index, string address, uint64_t amount, monero_send_priority priority);
|
||||
monero_tx_set send_split(const monero_send_request& request);
|
||||
vector<monero_tx_set> sweep_unlocked(const monero_send_request& request);
|
||||
monero_tx_set sweep_output(const monero_send_request& request);
|
||||
monero_tx_set sweep_dust(bool do_not_relay = false);
|
||||
monero_tx_set parse_tx_set(const monero_tx_set& tx_set);
|
||||
string sign(const string& msg) const;
|
||||
bool verify(const string& msg, const string& address, const string& signature) const;
|
||||
string get_tx_key(const string& tx_id) const;
|
||||
shared_ptr<monero_check_tx> check_tx_key(const string& tx_id, const string& txKey, const string& address) const;
|
||||
string get_tx_proof(const string& tx_id, const string& address, const string& message) const;
|
||||
shared_ptr<monero_check_tx> check_tx_proof(const string& tx_id, const string& address, const string& message, const string& signature) const;
|
||||
string get_spend_proof(const string& tx_id, const string& message) const;
|
||||
bool check_spend_proof(const string& tx_id, const string& message, const string& signature) const;
|
||||
string get_reserve_proof_wallet(const string& message) const;
|
||||
string get_reserve_proof_account(uint32_t account_idx, uint64_t amount, const string& message) const;
|
||||
shared_ptr<monero_check_reserve> check_reserve_proof(const string& address, const string& message, const string& signature) const;
|
||||
string get_tx_note(const string& tx_id) const;
|
||||
vector<string> get_tx_notes(const vector<string>& tx_ids) const;
|
||||
void set_tx_note(const string& tx_id, const string& note);
|
||||
void set_tx_notes(const vector<string>& tx_ids, const vector<string>& notes);
|
||||
vector<monero_address_book_entry> get_address_book_entries(const vector<uint64_t>& indices) const;
|
||||
uint64_t add_address_book_entry(const string& address, const string& description, const string& payment_id = "");
|
||||
void edit_address_book_entry(uint64_t index, bool set_address, const string& address, bool set_description, const string& description, bool set_payment_id = false, const string& payment_id = "");
|
||||
void delete_address_book_entry(uint64_t index);
|
||||
string create_payment_uri(const monero_send_request& request) const;
|
||||
shared_ptr<monero_send_request> parse_payment_uri(const string& uri) const;
|
||||
bool get_attribute(const string& key, string& value) const;
|
||||
void set_attribute(const string& key, const string& val);
|
||||
void start_mining(boost::optional<uint64_t> num_threads, boost::optional<bool> background_mining, boost::optional<bool> ignore_battery);
|
||||
void stop_mining();
|
||||
uint64_t wait_for_next_block();
|
||||
bool is_multisig_import_needed() const;
|
||||
monero_multisig_info get_multisig_info();
|
||||
string prepare_multisig();
|
||||
monero_multisig_init_result make_multisig(const vector<string>& multisig_hexes, int threshold, const string& password);
|
||||
monero_multisig_init_result exchange_multisig_keys(const vector<string>& mutisig_hexes, const string& password);
|
||||
string get_multisig_hex();
|
||||
int import_multisig_hex(const vector<string>& multisig_hexes);
|
||||
monero_multisig_sign_result sign_multisig_tx_hex(const string& multisig_tx_hex);
|
||||
vector<string> submit_multisig_tx_hex(const string& signed_multisig_tx_hex);
|
||||
void save();
|
||||
void move_to(string path, string password);
|
||||
void close(bool save = false);
|
||||
|
||||
// --------------------------------- PRIVATE --------------------------------
|
||||
|
||||
private:
|
||||
friend struct wallet2_listener;
|
||||
unique_ptr<tools::wallet2> m_w2; // internal wallet implementation
|
||||
unique_ptr<wallet2_listener> m_w2_listener; // internal wallet implementation listener
|
||||
set<monero_wallet_listener*> m_listeners; // external wallet listeners
|
||||
|
||||
void init_common();
|
||||
vector<monero_subaddress> get_subaddresses_aux(uint32_t account_idx, const vector<uint32_t>& subaddress_indices, const vector<tools::wallet2::transfer_details>& transfers) const;
|
||||
monero_tx_set sweep_account(const monero_send_request& request); // sweeps unlocked funds within an account; private helper to sweep_unlocked()
|
||||
|
||||
// blockchain sync management
|
||||
mutable std::atomic<bool> m_is_synced; // whether or not wallet is synced
|
||||
mutable std::atomic<bool> m_is_connected; // cache connection status to avoid unecessary RPC calls
|
||||
boost::condition_variable m_sync_cv; // to make sync threads woke
|
||||
boost::mutex m_sync_mutex; // synchronize sync() and syncAsync() requests
|
||||
std::atomic<bool> m_rescan_on_sync; // whether or not to rescan on sync
|
||||
std::atomic<bool> m_syncing_enabled; // whether or not auto sync is enabled
|
||||
std::atomic<int> m_syncing_interval; // auto sync loop interval in milliseconds
|
||||
boost::thread m_syncing_thread; // thread for auto sync loop
|
||||
boost::mutex m_syncing_mutex; // synchronize auto sync loop
|
||||
std::atomic<bool> m_syncing_thread_done; // whether or not the syncing thread is shut down
|
||||
void sync_thread_func(); // function to run thread with syncing loop
|
||||
monero_sync_result lock_and_sync(boost::optional<uint64_t> start_height = boost::none); // internal function to synchronize request to sync and rescan
|
||||
monero_sync_result sync_aux(boost::optional<uint64_t> start_height = boost::none); // internal function to immediately block, sync, and report progress
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2019 woodser
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Parts of this file are originally copyright (c) 2014-2019, The Monero Project
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
*/
|
||||
|
||||
#include "monero_wallet_keys.h"
|
||||
|
||||
#include "utils/monero_utils.h"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include "mnemonics/electrum-words.h"
|
||||
#include "mnemonics/english.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||
#include "string_tools.h"
|
||||
#include "device/device.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace epee;
|
||||
using namespace tools;
|
||||
using namespace crypto;
|
||||
|
||||
/**
|
||||
* Public library interface.
|
||||
*/
|
||||
namespace monero {
|
||||
|
||||
// ---------------------------- WALLET MANAGEMENT ---------------------------
|
||||
|
||||
monero_wallet_keys* monero_wallet_keys::create_wallet_random(const monero_network_type network_type, const string& language) {
|
||||
|
||||
// initialize random wallet account
|
||||
monero_wallet_keys* wallet = new monero_wallet_keys();
|
||||
crypto::secret_key spend_key_sk = wallet->m_account.generate();
|
||||
|
||||
// initialize remaining wallet
|
||||
wallet->m_network_type = network_type;
|
||||
wallet->m_language = language;
|
||||
epee::wipeable_string wipeable_mnemonic;
|
||||
if (!crypto::ElectrumWords::bytes_to_words(spend_key_sk, wipeable_mnemonic, wallet->m_language)) {
|
||||
throw runtime_error("Failed to create mnemonic from private spend key for language: " + string(wallet->m_language));
|
||||
}
|
||||
wallet->m_mnemonic = string(wipeable_mnemonic.data(), wipeable_mnemonic.size());
|
||||
wallet->init_common();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
monero_wallet_keys* monero_wallet_keys::create_wallet_from_mnemonic(const monero_network_type network_type, const string& mnemonic) {
|
||||
|
||||
// validate mnemonic and get recovery key and language
|
||||
crypto::secret_key recovery_key;
|
||||
string language;
|
||||
bool is_valid = crypto::ElectrumWords::words_to_bytes(mnemonic, recovery_key, language);
|
||||
if (!is_valid) throw runtime_error("Invalid mnemonic");
|
||||
if (language == crypto::ElectrumWords::old_language_name) language = Language::English().get_language_name();
|
||||
|
||||
// initialize wallet account
|
||||
monero_wallet_keys* wallet = new monero_wallet_keys();
|
||||
wallet->m_account = cryptonote::account_base{};
|
||||
wallet->m_account.generate(recovery_key, true, false);
|
||||
|
||||
// initialize remaining wallet
|
||||
wallet->m_network_type = network_type;
|
||||
wallet->m_mnemonic = mnemonic;
|
||||
wallet->m_language = language;
|
||||
wallet->init_common();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
monero_wallet_keys* monero_wallet_keys::create_wallet_from_keys(const monero_network_type network_type, const string& address, const string& view_key, const string& spend_key, const string& language) {
|
||||
|
||||
// validate and parse address
|
||||
cryptonote::address_parse_info info;
|
||||
if (!cryptonote::get_account_address_from_str(info, static_cast<cryptonote::network_type>(network_type), address)) throw runtime_error("failed to parse address");
|
||||
|
||||
// validate and parse optional private spend key
|
||||
crypto::secret_key spend_key_sk;
|
||||
bool has_spend_key = false;
|
||||
if (!spend_key.empty()) {
|
||||
cryptonote::blobdata spend_key_data;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(spend_key, spend_key_data) || spend_key_data.size() != sizeof(crypto::secret_key)) {
|
||||
throw runtime_error("failed to parse secret spend key");
|
||||
}
|
||||
has_spend_key = true;
|
||||
spend_key_sk = *reinterpret_cast<const crypto::secret_key*>(spend_key_data.data());
|
||||
}
|
||||
|
||||
// validate and parse private view key
|
||||
bool has_view_key = true;
|
||||
crypto::secret_key view_key_sk;
|
||||
if (view_key.empty()) {
|
||||
if (has_spend_key) has_view_key = false;
|
||||
else throw runtime_error("Neither view key nor spend key supplied, cancelled");
|
||||
}
|
||||
if (has_view_key) {
|
||||
cryptonote::blobdata view_key_data;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(view_key, view_key_data) || view_key_data.size() != sizeof(crypto::secret_key)) {
|
||||
throw runtime_error("failed to parse secret view key");
|
||||
}
|
||||
view_key_sk = *reinterpret_cast<const crypto::secret_key*>(view_key_data.data());
|
||||
}
|
||||
|
||||
// check the spend and view keys match the given address
|
||||
crypto::public_key pkey;
|
||||
if (has_spend_key) {
|
||||
if (!crypto::secret_key_to_public_key(spend_key_sk, pkey)) throw runtime_error("failed to verify secret spend key");
|
||||
if (info.address.m_spend_public_key != pkey) throw runtime_error("spend key does not match address");
|
||||
}
|
||||
if (has_view_key) {
|
||||
if (!crypto::secret_key_to_public_key(view_key_sk, pkey)) throw runtime_error("failed to verify secret view key");
|
||||
if (info.address.m_view_public_key != pkey) throw runtime_error("view key does not match address");
|
||||
}
|
||||
|
||||
// initialize wallet account
|
||||
monero_wallet_keys* wallet = new monero_wallet_keys();
|
||||
if (has_spend_key && has_view_key) {
|
||||
wallet->m_account.create_from_keys(info.address, spend_key_sk, view_key_sk);
|
||||
} else if (has_spend_key) {
|
||||
wallet->m_account.generate(spend_key_sk, true, false);
|
||||
} else {
|
||||
wallet->m_account.create_from_viewkey(info.address, view_key_sk);
|
||||
}
|
||||
|
||||
// initialize remaining wallet
|
||||
wallet->m_network_type = network_type;
|
||||
wallet->m_language = language;
|
||||
epee::wipeable_string wipeable_mnemonic;
|
||||
if (!crypto::ElectrumWords::bytes_to_words(spend_key_sk, wipeable_mnemonic, wallet->m_language)) {
|
||||
throw runtime_error("Failed to create mnemonic from private spend key for language: " + string(wallet->m_language));
|
||||
}
|
||||
wallet->m_mnemonic = string(wipeable_mnemonic.data(), wipeable_mnemonic.size());
|
||||
wallet->init_common();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
// ----------------------------- WALLET METHODS -----------------------------
|
||||
|
||||
monero_wallet_keys::~monero_wallet_keys() {
|
||||
MTRACE("~monero_wallet_keys()");
|
||||
close();
|
||||
}
|
||||
|
||||
monero_version monero_wallet_keys::get_version() const {
|
||||
monero_version version;
|
||||
version.m_number = 65552; // same as monero-wallet-rpc v0.15.0.1 release
|
||||
version.m_is_release = false; // TODO: could pull from MONERO_VERSION_IS_RELEASE in version.cpp
|
||||
return version;
|
||||
}
|
||||
|
||||
vector<string> monero_wallet_keys::get_languages() const {
|
||||
cout << "monero_wallet_keys::get_languages()" << endl;
|
||||
throw runtime_error("monero_wallet_keys::get_languages() not implemented");
|
||||
}
|
||||
|
||||
string monero_wallet_keys::get_address(uint32_t account_idx, uint32_t subaddress_idx) const {
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
cryptonote::subaddress_index index{account_idx, subaddress_idx};
|
||||
cryptonote::account_public_address address = hwdev.get_subaddress(m_account.get_keys(), index);
|
||||
return cryptonote::get_account_address_as_str(static_cast<cryptonote::network_type>(m_network_type), !index.is_zero(), address);
|
||||
}
|
||||
|
||||
monero_integrated_address monero_wallet_keys::get_integrated_address(const string& standard_address, const string& payment_id) const {
|
||||
cout << "monero_wallet_keys::get_integrated_address()" << endl;
|
||||
throw runtime_error("monero_wallet_keys::get_integrated_address() not implemented");
|
||||
}
|
||||
|
||||
monero_integrated_address monero_wallet_keys::decode_integrated_address(const string& integrated_address) const {
|
||||
cout << "monero_wallet_keys::decode_integrated_address()" << endl;
|
||||
throw runtime_error("monero_wallet_keys::decode_integrated_address() not implemented");
|
||||
}
|
||||
|
||||
monero_account monero_wallet_keys::get_account(uint32_t account_idx, bool include_subaddresses) const {
|
||||
cout << "monero_wallet_keys::get_account()" << endl;
|
||||
|
||||
if (include_subaddresses) {
|
||||
string err = "monero_wallet_keys::get_account(account_idx, include_subaddresses) include_subaddresses must be false";
|
||||
cout << err << endl;
|
||||
throw runtime_error(err);
|
||||
}
|
||||
|
||||
// build and return account
|
||||
monero_account account;
|
||||
account.m_index = account_idx;
|
||||
account.m_primary_address = get_address(account_idx, 0);
|
||||
return account;
|
||||
}
|
||||
|
||||
vector<monero_subaddress> monero_wallet_keys::get_subaddresses(const uint32_t account_idx, const vector<uint32_t>& subaddress_indices) const {
|
||||
|
||||
// must provide subaddress indices
|
||||
if (subaddress_indices.empty()) {
|
||||
string err = "Keys-only wallet does not have enumerable set of subaddresses; specific specific subaddresses";
|
||||
cout << err << endl;
|
||||
throw runtime_error(err);
|
||||
}
|
||||
|
||||
// initialize subaddresses at indices
|
||||
vector<monero_subaddress> subaddresses;
|
||||
for (uint32_t subaddressIndicesIdx = 0; subaddressIndicesIdx < subaddress_indices.size(); subaddressIndicesIdx++) {
|
||||
monero_subaddress subaddress;
|
||||
subaddress.m_account_index = account_idx;
|
||||
uint32_t subaddress_idx = subaddress_indices.at(subaddressIndicesIdx);
|
||||
subaddress.m_index = subaddress_idx;
|
||||
subaddress.m_address = get_address(account_idx, subaddress_idx);
|
||||
subaddresses.push_back(subaddress);
|
||||
}
|
||||
|
||||
return subaddresses;
|
||||
}
|
||||
|
||||
string monero_wallet_keys::sign(const string& msg) const {
|
||||
cout << "monero_wallet_keys::sign()" << endl;
|
||||
throw runtime_error("monero_wallet_keys::sign() not implemented");
|
||||
}
|
||||
|
||||
bool monero_wallet_keys::verify(const string& msg, const string& address, const string& signature) const {
|
||||
cout << "monero_wallet_keys::verify()" << endl;
|
||||
throw runtime_error("monero_wallet_keys::verify() not implemented");
|
||||
}
|
||||
|
||||
void monero_wallet_keys::close(bool save) {
|
||||
if (save) throw runtime_error("MoneroWalletKeys does not support saving");
|
||||
// no pointers to destroy
|
||||
}
|
||||
|
||||
// ------------------------------- PRIVATE HELPERS ----------------------------
|
||||
|
||||
void monero_wallet_keys::init_common() {
|
||||
m_primary_address = m_account.get_public_address_str(static_cast<cryptonote::network_type>(m_network_type));
|
||||
const cryptonote::account_keys& keys = m_account.get_keys();
|
||||
m_pub_view_key = epee::string_tools::pod_to_hex(keys.m_account_address.m_view_public_key);
|
||||
m_prv_view_key = epee::string_tools::pod_to_hex(keys.m_view_secret_key);
|
||||
m_pub_spend_key = epee::string_tools::pod_to_hex(keys.m_account_address.m_spend_public_key);
|
||||
m_prv_spend_key = epee::string_tools::pod_to_hex(keys.m_spend_secret_key);
|
||||
if (m_prv_spend_key == "0000000000000000000000000000000000000000000000000000000000000000") m_prv_spend_key = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2019 woodser
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Parts of this file are originally copyright (c) 2014-2019, The Monero Project
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "monero_wallet.h"
|
||||
#include "cryptonote_basic/account.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace monero;
|
||||
|
||||
/**
|
||||
* Public library interface.
|
||||
*/
|
||||
namespace monero {
|
||||
|
||||
/**
|
||||
* Monero wallet implementation to provide basic offline key management.
|
||||
*/
|
||||
class monero_wallet_keys : public monero_wallet {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create a new wallet with a randomly generated seed.
|
||||
*
|
||||
* @param network_type is the wallet's network type (default = monero_network_type.MAINNET)
|
||||
* @param language is the wallet and mnemonic's language (default = "English")
|
||||
*/
|
||||
static monero_wallet_keys* create_wallet_random(const monero_network_type network_type, const string& language);
|
||||
|
||||
/**
|
||||
* Create a wallet from an existing mnemonic phrase.
|
||||
*
|
||||
* @param network_type is the wallet's network type
|
||||
* @param mnemonic is the mnemonic of the wallet to construct
|
||||
*/
|
||||
static monero_wallet_keys* create_wallet_from_mnemonic(const monero_network_type network_type, const string& mnemonic);
|
||||
|
||||
/**
|
||||
* Create a wallet from an address, view key, and spend key.
|
||||
*
|
||||
* @param network_type is the wallet's network type
|
||||
* @param address is the address of the wallet to construct
|
||||
* @param view_key is the private view key of the wallet to construct
|
||||
* @param spend_key is the private spend key of the wallet to construct
|
||||
* @param language is the wallet and mnemonic's language (default = "English")
|
||||
*/
|
||||
static monero_wallet_keys* create_wallet_from_keys(const monero_network_type network_type, const string& address, const string& view_key, const string& spend_key, const string& language = "English");
|
||||
|
||||
/**
|
||||
* Destruct the wallet.
|
||||
*/
|
||||
~monero_wallet_keys();
|
||||
|
||||
/**
|
||||
* Supported wallet methods.
|
||||
*/
|
||||
monero_version get_version() const;
|
||||
monero_network_type get_network_type() const { return m_network_type; }
|
||||
string get_mnemonic() const { return m_mnemonic; }
|
||||
string get_language() const { return m_language; }
|
||||
vector<string> get_languages() const;
|
||||
string get_private_view_key() const { return m_prv_view_key; }
|
||||
string get_private_spend_key() const { return m_prv_spend_key; }
|
||||
string get_public_view_key() const { return m_pub_view_key; }
|
||||
string get_public_spend_key() const { return m_pub_spend_key; }
|
||||
string get_primary_address() const { return m_primary_address; }
|
||||
string get_address(const uint32_t account_idx, const uint32_t subaddress_idx) const;
|
||||
monero_integrated_address get_integrated_address(const string& standard_address = "", const string& payment_id = "") const;
|
||||
monero_integrated_address decode_integrated_address(const string& integrated_address) const;
|
||||
monero_account get_account(const uint32_t account_idx, bool include_subaddresses) const;
|
||||
vector<monero_subaddress> get_subaddresses(const uint32_t account_idx, const vector<uint32_t>& subaddress_indices) const;
|
||||
string sign(const string& msg) const;
|
||||
bool verify(const string& msg, const string& address, const string& signature) const;
|
||||
void close(bool save = false);
|
||||
|
||||
// --------------------------------- PRIVATE --------------------------------
|
||||
|
||||
private:
|
||||
monero_network_type m_network_type;
|
||||
cryptonote::account_base m_account;
|
||||
string m_mnemonic;
|
||||
string m_language;
|
||||
string m_pub_view_key;
|
||||
string m_prv_view_key;
|
||||
string m_pub_spend_key;
|
||||
string m_prv_spend_key;
|
||||
string m_primary_address;
|
||||
|
||||
void init_common();
|
||||
};
|
||||
}
|
||||
@@ -54,7 +54,6 @@
|
||||
|
||||
#include "utils/gen_utils.h"
|
||||
#include "utils/monero_utils.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Reference in New Issue
Block a user