aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.cpp3
-rw-r--r--src/ringct/rctSigs.cpp4
-rw-r--r--src/ringct/rctSigs.h4
-rw-r--r--src/ringct/rctTypes.h2
-rw-r--r--src/wallet/api/transaction_history.cpp41
-rw-r--r--src/wallet/api/transaction_history.h2
-rw-r--r--src/wallet/api/wallet.cpp43
-rw-r--r--src/wallet/api/wallet.h5
-rw-r--r--src/wallet/api/wallet_manager.cpp5
-rw-r--r--src/wallet/api/wallet_manager.h2
-rw-r--r--src/wallet/wallet2.cpp11
-rw-r--r--src/wallet/wallet2_api.h24
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