diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptonote_core/cryptonote_format_utils.cpp | 3 | ||||
-rw-r--r-- | src/ringct/rctSigs.cpp | 4 | ||||
-rw-r--r-- | src/ringct/rctSigs.h | 4 | ||||
-rw-r--r-- | src/ringct/rctTypes.h | 2 | ||||
-rw-r--r-- | src/wallet/api/transaction_history.cpp | 41 | ||||
-rw-r--r-- | src/wallet/api/transaction_history.h | 2 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 43 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 5 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.cpp | 5 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.h | 2 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 11 | ||||
-rw-r--r-- | src/wallet/wallet2_api.h | 24 |
12 files changed, 112 insertions, 34 deletions
diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 64f8eb924..870e8f0d8 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -658,10 +658,7 @@ namespace cryptonote } else { - bool all_rct_inputs = true; size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct - BOOST_FOREACH(const tx_source_entry& src_entr, sources) - all_rct_inputs &= !(src_entr.mask == rct::identity()); // the non-simple version is slightly smaller, but assumes all real inputs // are on the same index, so can only be used if there just one ring. diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index ed1f8cc0e..85d21e805 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -150,7 +150,7 @@ namespace rct { // Gen creates a signature which proves that for some column in the keymatrix "pk" // the signer knows a secret key for each row in that column // Ver verifies that the MG sig was created correctly - mgSig MLSAG_Gen(key message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows) { + mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows) { mgSig rv; size_t cols = pk.size(); CHECK_AND_ASSERT_THROW_MES(cols >= 2, "Error! What is c if cols = 1!"); @@ -239,7 +239,7 @@ namespace rct { // Gen creates a signature which proves that for some column in the keymatrix "pk" // the signer knows a secret key for each row in that column // Ver verifies that the MG sig was created correctly - bool MLSAG_Ver(key message, const keyM & pk, const mgSig & rv, size_t dsRows) { + bool MLSAG_Ver(const key &message, const keyM & pk, const mgSig & rv, size_t dsRows) { size_t cols = pk.size(); CHECK_AND_ASSERT_MES(cols >= 2, false, "Error! What is c if cols = 1!"); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index f1c906d5e..11d771818 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -90,8 +90,8 @@ namespace rct { // the signer knows a secret key for each row in that column // Ver verifies that the MG sig was created correctly keyV keyImageV(const keyV &xx); - mgSig MLSAG_Gen(key message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows); - bool MLSAG_Ver(key message, const keyM &pk, const mgSig &sig, size_t dsRows); + mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows); + bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &sig, size_t dsRows); //mgSig MLSAG_Gen_Old(const keyM & pk, const keyV & xx, const int index); //proveRange and verRange diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index bfafebb83..25f6f9bc9 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -415,7 +415,7 @@ namespace rct { // then the value in the first 8 bytes is returned xmr_amount h2d(const key &test); //32 byte key to int[64] - void h2b(bits amountb2, key & test); + void h2b(bits amountb2, const key & test); //int[64] to 32 byte key void b2h(key & amountdh, bits amountb2); //int[64] to uint long long diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index 95aafb04f..e4a003b02 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.cpp @@ -60,21 +60,44 @@ TransactionHistoryImpl::~TransactionHistoryImpl() int TransactionHistoryImpl::count() const { - return m_history.size(); + boost::shared_lock<boost::shared_mutex> lock(m_historyMutex); + int result = m_history.size(); + return result; +} + +TransactionInfo *TransactionHistoryImpl::transaction(int index) const +{ + boost::shared_lock<boost::shared_mutex> lock(m_historyMutex); + // sanity check + if (index < 0) + return nullptr; + unsigned index_ = static_cast<unsigned>(index); + return index_ < m_history.size() ? m_history[index_] : nullptr; } TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) const { - return nullptr; + boost::shared_lock<boost::shared_mutex> lock(m_historyMutex); + auto itr = std::find_if(m_history.begin(), m_history.end(), + [&](const TransactionInfo * ti) { + return ti->hash() == id; + }); + return itr != m_history.end() ? *itr : nullptr; } std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const { + boost::shared_lock<boost::shared_mutex> lock(m_historyMutex); return m_history; } void TransactionHistoryImpl::refresh() { + // multithreaded access: + // boost::lock_guard<boost::mutex> guarg(m_historyMutex); + // for "write" access, locking exclusively + boost::unique_lock<boost::shared_mutex> lock(m_historyMutex); + // TODO: configurable values; uint64_t min_height = 0; uint64_t max_height = (uint64_t)-1; @@ -84,8 +107,6 @@ void TransactionHistoryImpl::refresh() delete t; m_history.clear(); - - // transactions are stored in wallet2: // - confirmed_transfer_details - out transfers // - unconfirmed_transfer_details - pending out transfers @@ -109,7 +130,7 @@ void TransactionHistoryImpl::refresh() ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash); ti->m_blockheight = pd.m_block_height; // TODO: - // ti->m_timestamp = pd.m_timestamp; + ti->m_timestamp = pd.m_timestamp; m_history.push_back(ti); /* output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, (boost::format("%20.20s %s %s %s") @@ -151,6 +172,7 @@ void TransactionHistoryImpl::refresh() ti->m_direction = TransactionInfo::Direction_Out; ti->m_hash = string_tools::pod_to_hex(hash); ti->m_blockheight = pd.m_block_height; + ti->m_timestamp = pd.m_timestamp; // single output transaction might contain multiple transfers for (const auto &d: pd.m_dests) { @@ -180,14 +202,9 @@ void TransactionHistoryImpl::refresh() ti->m_failed = is_failed; ti->m_pending = true; ti->m_hash = string_tools::pod_to_hex(hash); + ti->m_timestamp = pd.m_timestamp; m_history.push_back(ti); } - -} - -TransactionInfo *TransactionHistoryImpl::transaction(int index) const -{ - return nullptr; } -} +} // namespace diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h index 171fd2210..1b6617ead 100644 --- a/src/wallet/api/transaction_history.h +++ b/src/wallet/api/transaction_history.h @@ -29,6 +29,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "wallet/wallet2_api.h" +#include <boost/thread/shared_mutex.hpp> namespace Bitmonero { @@ -51,6 +52,7 @@ private: // TransactionHistory is responsible of memory management std::vector<TransactionInfo*> m_history; WalletImpl *m_wallet; + mutable boost::shared_mutex m_historyMutex; }; } diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 4d35bc404..d1c849537 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -54,8 +54,9 @@ namespace { struct Wallet2CallbackImpl : public tools::i_wallet2_callback { - Wallet2CallbackImpl() + Wallet2CallbackImpl(WalletImpl * wallet) : m_listener(nullptr) + , m_wallet(wallet) { } @@ -93,7 +94,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback LOG_PRINT_L3(__FUNCTION__ << ": money received. height: " << height << ", tx: " << tx_hash << ", amount: " << print_money(amount)); - if (m_listener) { + // do not signal on received tx if wallet is not syncronized completely + if (m_listener && m_wallet->synchronized()) { m_listener->moneyReceived(tx_hash, amount); m_listener->updated(); } @@ -107,7 +109,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback LOG_PRINT_L3(__FUNCTION__ << ": money spent. height: " << height << ", tx: " << tx_hash << ", amount: " << print_money(amount)); - if (m_listener) { + // do not signal on sent tx if wallet is not syncronized completely + if (m_listener && m_wallet->synchronized()) { m_listener->moneySpent(tx_hash, amount); m_listener->updated(); } @@ -119,6 +122,7 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback } WalletListener * m_listener; + WalletImpl * m_wallet; }; Wallet::~Wallet() {} @@ -166,12 +170,16 @@ uint64_t Wallet::maximumAllowedAmount() ///////////////////////// WalletImpl implementation //////////////////////// WalletImpl::WalletImpl(bool testnet) - :m_wallet(nullptr), m_status(Wallet::Status_Ok), m_trustedDaemon(false), - m_wallet2Callback(nullptr), m_recoveringFromSeed(false) + :m_wallet(nullptr) + , m_status(Wallet::Status_Ok) + , m_trustedDaemon(false) + , m_wallet2Callback(nullptr) + , m_recoveringFromSeed(false) + , m_synchronized(false) { m_wallet = new tools::wallet2(testnet); m_history = new TransactionHistoryImpl(this); - m_wallet2Callback = new Wallet2CallbackImpl; + m_wallet2Callback = new Wallet2CallbackImpl(this); m_wallet->callback(m_wallet2Callback); m_refreshThreadDone = false; m_refreshEnabled = false; @@ -201,7 +209,6 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co bool keys_file_exists; bool wallet_file_exists; tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists); - // TODO: figure out how to setup logger; LOG_PRINT_L3("wallet_path: " << path << ""); LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha << " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha); @@ -404,7 +411,15 @@ void WalletImpl::initAsync(const string &daemon_address, uint64_t upper_transact startRefresh(); } +void WalletImpl::setRefreshFromBlockHeight(uint64_t refresh_from_block_height) +{ + m_wallet->set_refresh_from_block_height(refresh_from_block_height); +} +void WalletImpl::setRecoveringFromSeed(bool recoveringFromSeed) +{ + m_recoveringFromSeed = recoveringFromSeed; +} uint64_t WalletImpl::balance() const { @@ -455,6 +470,11 @@ uint64_t WalletImpl::daemonBlockChainTargetHeight() const return result; } +bool WalletImpl::synchronized() const +{ + return m_synchronized; +} + bool WalletImpl::refresh() { clearStatus(); @@ -723,6 +743,15 @@ void WalletImpl::doRefresh() boost::lock_guard<boost::mutex> guarg(m_refreshMutex2); try { m_wallet->refresh(); + if (!m_synchronized) { + m_synchronized = true; + } + // assuming if we have empty history, it wasn't initialized yet + // for futher history changes client need to update history in + // "on_money_received" and "on_money_sent" callbacks + if (m_history->count() == 0) { + m_history->refresh(); + } } catch (const std::exception &e) { m_status = Status_Error; m_errorString = e.what(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index c399e3ab6..c8a59f7c3 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -78,10 +78,13 @@ public: uint64_t blockChainHeight() const; uint64_t daemonBlockChainHeight() const; uint64_t daemonBlockChainTargetHeight() const; + bool synchronized() const; bool refresh(); void refreshAsync(); void setAutoRefreshInterval(int millis); int autoRefreshInterval() const; + void setRefreshFromBlockHeight(uint64_t refresh_from_block_height); + void setRecoveringFromSeed(bool recoveringFromSeed); @@ -108,6 +111,7 @@ private: private: friend class PendingTransactionImpl; friend class TransactionHistoryImpl; + friend class Wallet2CallbackImpl; tools::wallet2 * m_wallet; mutable std::atomic<int> m_status; @@ -133,6 +137,7 @@ private: // so it shouldn't be considered as new and pull blocks (slow-refresh) // instead of pulling hashes (fast-refresh) bool m_recoveringFromSeed; + std::atomic<bool> m_synchronized; }; diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index ca83806ff..aa99476ee 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -57,9 +57,12 @@ Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string return wallet; } -Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &memo, bool testnet) +Wallet *WalletManagerImpl::recoveryWallet(const std::string &path, const std::string &memo, bool testnet, uint64_t restoreHeight) { WalletImpl * wallet = new WalletImpl(testnet); + if(restoreHeight > 0){ + wallet->setRefreshFromBlockHeight(restoreHeight); + } wallet->recover(path, memo); return wallet; } diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 7585c1af7..2e932a2a1 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -40,7 +40,7 @@ public: Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet); Wallet * openWallet(const std::string &path, const std::string &password, bool testnet); - virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet); + virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet, uint64_t restoreHeight); virtual bool closeWallet(Wallet *wallet); bool walletExists(const std::string &path); std::vector<std::string> findWallets(const std::string &path); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 61c3a5149..98dbc4fd6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -583,11 +583,14 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s std::string(", expected ") + print_money(td.amount())); } amount = td.amount(); - LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << txid()); tx_money_spent_in_ins += amount; - set_spent(it->second, height); - if (0 != m_callback) - m_callback->on_money_spent(height, tx, amount, tx); + if (!pool) + { + LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << txid()); + set_spent(it->second, height); + if (0 != m_callback) + m_callback->on_money_spent(height, tx, amount, tx); + } } } diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 8d5223006..0f622c26c 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -219,6 +219,20 @@ struct Wallet */ virtual void initAsync(const std::string &daemon_address, uint64_t upper_transaction_size_limit) = 0; + /*! + * \brief setRefreshFromBlockHeight - start refresh from block height on recover + * + * \param refresh_from_block_height - blockchain start height + */ + virtual void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) = 0; + + /*! + * \brief setRecoveringFromSeed - set state recover form seed + * + * \param recoveringFromSeed - true/false + */ + virtual void setRecoveringFromSeed(bool recoveringFromSeed) = 0; + /** * @brief connectToDaemon - connects to the daemon. TODO: check if it can be removed * @return @@ -255,6 +269,12 @@ struct Wallet */ virtual uint64_t daemonBlockChainTargetHeight() const = 0; + /** + * @brief synchronized - checks if wallet was ever synchronized + * @return + */ + virtual bool synchronized() const = 0; + static std::string displayAmount(uint64_t amount); static uint64_t amountFromString(const std::string &amount); static uint64_t amountFromDouble(double amount); @@ -347,9 +367,11 @@ struct WalletManager * \brief recovers existing wallet using memo (electrum seed) * \param path Name of wallet file to be created * \param memo memo (25 words electrum seed) + * \param testnet testnet + * \param restoreHeight restore from start height * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully) */ - virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet = false) = 0; + virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet = false, uint64_t restoreHeight = 0) = 0; /*! * \brief Closes wallet. In case operation succeded, wallet object deleted. in case operation failed, wallet object not deleted |