aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/blockchain_db.cpp4
-rw-r--r--src/blockchain_db/blockchain_db.h55
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp76
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h11
-rw-r--r--src/blockchain_db/testdb.h10
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp6
-rw-r--r--src/common/combinator.h1
-rw-r--r--src/common/dns_utils.cpp7
-rw-r--r--src/crypto/crypto.h27
-rw-r--r--src/cryptonote_basic/difficulty.cpp15
-rw-r--r--src/cryptonote_basic/difficulty.h3
-rw-r--r--src/cryptonote_basic/hardfork.cpp8
-rw-r--r--src/cryptonote_core/blockchain.cpp53
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp5
-rw-r--r--src/device/device.hpp1
-rw-r--r--src/device_trezor/device_trezor_base.cpp13
-rw-r--r--src/device_trezor/device_trezor_base.hpp2
-rw-r--r--src/device_trezor/trezor/transport.cpp64
-rw-r--r--src/device_trezor/trezor/transport.hpp10
-rw-r--r--src/p2p/net_node.inl13
-rw-r--r--src/p2p/net_peerlist.h2
-rw-r--r--src/ringct/rctSigs.cpp1
-rw-r--r--src/ringct/rctTypes.h2
-rw-r--r--src/rpc/core_rpc_server.cpp8
-rw-r--r--src/simplewallet/simplewallet.cpp6
-rw-r--r--src/wallet/api/wallet.cpp12
-rw-r--r--src/wallet/api/wallet2_api.h27
-rw-r--r--src/wallet/api/wallet_manager.cpp15
-rw-r--r--src/wallet/api/wallet_manager.h5
-rw-r--r--src/wallet/wallet2.cpp60
-rw-r--r--src/wallet/wallet2.h9
-rw-r--r--src/wallet/wallet_rpc_server.cpp91
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h14
33 files changed, 429 insertions, 207 deletions
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp
index d772bf4bb..2b039f557 100644
--- a/src/blockchain_db/blockchain_db.cpp
+++ b/src/blockchain_db/blockchain_db.cpp
@@ -211,8 +211,6 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
if (blk.tx_hashes.size() != txs.size())
throw std::runtime_error("Inconsistent tx/hashes sizes");
- block_txn_start(false);
-
TIME_MEASURE_START(time1);
crypto::hash blk_hash = get_block_hash(blk);
TIME_MEASURE_FINISH(time1);
@@ -252,8 +250,6 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
m_hardfork->add(blk, prev_height);
- block_txn_stop();
-
++num_calls;
return prev_height;
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 2c40b5a78..567be6a65 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -770,9 +770,12 @@ public:
*/
virtual void set_batch_transactions(bool) = 0;
- virtual void block_txn_start(bool readonly=false) = 0;
- virtual void block_txn_stop() = 0;
- virtual void block_txn_abort() = 0;
+ virtual void block_wtxn_start() = 0;
+ virtual void block_wtxn_stop() = 0;
+ virtual void block_wtxn_abort() = 0;
+ virtual bool block_rtxn_start() const = 0;
+ virtual void block_rtxn_stop() const = 0;
+ virtual void block_rtxn_abort() const = 0;
virtual void set_hard_fork(HardFork* hf);
@@ -1699,6 +1702,52 @@ public:
}; // class BlockchainDB
+class db_txn_guard
+{
+public:
+ db_txn_guard(BlockchainDB *db, bool readonly): db(db), readonly(readonly), active(false)
+ {
+ if (readonly)
+ {
+ active = db->block_rtxn_start();
+ }
+ else
+ {
+ db->block_wtxn_start();
+ active = true;
+ }
+ }
+ virtual ~db_txn_guard()
+ {
+ if (active)
+ stop();
+ }
+ void stop()
+ {
+ if (readonly)
+ db->block_rtxn_stop();
+ else
+ db->block_wtxn_stop();
+ active = false;
+ }
+ void abort()
+ {
+ if (readonly)
+ db->block_rtxn_abort();
+ else
+ db->block_wtxn_abort();
+ active = false;
+ }
+
+private:
+ BlockchainDB *db;
+ bool readonly;
+ bool active;
+};
+
+class db_rtxn_guard: public db_txn_guard { public: db_rtxn_guard(BlockchainDB *db): db_txn_guard(db, true) {} };
+class db_wtxn_guard: public db_txn_guard { public: db_wtxn_guard(BlockchainDB *db): db_txn_guard(db, false) {} };
+
BlockchainDB *new_db(const std::string& db_type);
} // namespace cryptonote
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index a07e9ac55..340434888 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -3611,16 +3611,15 @@ void BlockchainLMDB::block_rtxn_stop() const
memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
}
-void BlockchainLMDB::block_txn_start(bool readonly)
+bool BlockchainLMDB::block_rtxn_start() const
{
- if (readonly)
- {
- MDB_txn *mtxn;
- mdb_txn_cursors *mcur;
- block_rtxn_start(&mtxn, &mcur);
- return;
- }
+ MDB_txn *mtxn;
+ mdb_txn_cursors *mcur;
+ return block_rtxn_start(&mtxn, &mcur);
+}
+void BlockchainLMDB::block_wtxn_start()
+{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
// Distinguish the exceptions here from exceptions that would be thrown while
// using the txn and committing it.
@@ -3652,10 +3651,13 @@ void BlockchainLMDB::block_txn_start(bool readonly)
throw0(DB_ERROR_TXN_START((std::string("Attempted to start new write txn when batch txn already exists in ")+__FUNCTION__).c_str()));
}
-void BlockchainLMDB::block_txn_stop()
+void BlockchainLMDB::block_wtxn_stop()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- if (m_write_txn && m_writer == boost::this_thread::get_id())
+ if (!m_write_txn)
+ throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn when no such txn exists in ")+__FUNCTION__).c_str()));
+ if (m_writer != boost::this_thread::get_id())
+ throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn from the wrong thread in ")+__FUNCTION__).c_str()));
{
if (! m_batch_active)
{
@@ -3669,40 +3671,31 @@ void BlockchainLMDB::block_txn_stop()
memset(&m_wcursors, 0, sizeof(m_wcursors));
}
}
- else if (m_tinfo->m_ti_rtxn)
- {
- mdb_txn_reset(m_tinfo->m_ti_rtxn);
- memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
- }
}
-void BlockchainLMDB::block_txn_abort()
+void BlockchainLMDB::block_wtxn_abort()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- if (m_write_txn && m_writer == boost::this_thread::get_id())
- {
- if (! m_batch_active)
- {
- delete m_write_txn;
- m_write_txn = nullptr;
- memset(&m_wcursors, 0, sizeof(m_wcursors));
- }
- }
- else if (m_tinfo->m_ti_rtxn)
- {
- mdb_txn_reset(m_tinfo->m_ti_rtxn);
- memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
- }
- else
+ if (!m_write_txn)
+ throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn when no such txn exists in ")+__FUNCTION__).c_str()));
+ if (m_writer != boost::this_thread::get_id())
+ throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn from the wrong thread in ")+__FUNCTION__).c_str()));
+
+ if (! m_batch_active)
{
- // This would probably mean an earlier exception was caught, but then we
- // proceeded further than we should have.
- throw0(DB_ERROR((std::string("BlockchainLMDB::") + __func__ +
- std::string(": block-level DB transaction abort called when write txn doesn't exist")
- ).c_str()));
+ delete m_write_txn;
+ m_write_txn = nullptr;
+ memset(&m_wcursors, 0, sizeof(m_wcursors));
}
}
+void BlockchainLMDB::block_rtxn_abort() const
+{
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ mdb_txn_reset(m_tinfo->m_ti_rtxn);
+ memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
+}
+
uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
const std::vector<std::pair<transaction, blobdata>>& txs)
{
@@ -3728,11 +3721,6 @@ uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t
{
throw;
}
- catch (...)
- {
- block_txn_abort();
- throw;
- }
return ++m_height;
}
@@ -3742,16 +3730,16 @@ void BlockchainLMDB::pop_block(block& blk, std::vector<transaction>& txs)
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
- block_txn_start(false);
+ block_wtxn_start();
try
{
BlockchainDB::pop_block(blk, txs);
- block_txn_stop();
+ block_wtxn_stop();
}
catch (...)
{
- block_txn_abort();
+ block_wtxn_abort();
throw;
}
}
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index f6b00817d..4b46f081e 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -310,11 +310,14 @@ public:
virtual void batch_stop();
virtual void batch_abort();
- virtual void block_txn_start(bool readonly);
- virtual void block_txn_stop();
- virtual void block_txn_abort();
- virtual bool block_rtxn_start(MDB_txn **mtxn, mdb_txn_cursors **mcur) const;
+ virtual void block_wtxn_start();
+ virtual void block_wtxn_stop();
+ virtual void block_wtxn_abort();
+ virtual bool block_rtxn_start() const;
virtual void block_rtxn_stop() const;
+ virtual void block_rtxn_abort() const;
+
+ bool block_rtxn_start(MDB_txn **mtxn, mdb_txn_cursors **mcur) const;
virtual void pop_block(block& blk, std::vector<transaction>& txs);
diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h
index 04fad26a4..1492fb2ae 100644
--- a/src/blockchain_db/testdb.h
+++ b/src/blockchain_db/testdb.h
@@ -55,9 +55,13 @@ public:
virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0) { return true; }
virtual void batch_stop() {}
virtual void set_batch_transactions(bool) {}
- virtual void block_txn_start(bool readonly=false) {}
- virtual void block_txn_stop() {}
- virtual void block_txn_abort() {}
+ virtual void block_wtxn_start() {}
+ virtual void block_wtxn_stop() {}
+ virtual void block_wtxn_abort() {}
+ virtual bool block_rtxn_start() const { return true; }
+ virtual void block_rtxn_stop() const {}
+ virtual void block_rtxn_abort() const {}
+
virtual void drop_hard_fork_info() {}
virtual bool block_exists(const crypto::hash& h, uint64_t *height) const { return false; }
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t& height) const { return cryptonote::t_serializable_object_to_blob(get_block_from_height(height)); }
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index 8454595ac..cb9154f29 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -194,7 +194,11 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
core.prevalidate_block_hashes(core.get_blockchain_storage().get_db().height(), hashes);
std::vector<block> pblocks;
- core.prepare_handle_incoming_blocks(blocks, pblocks);
+ if (!core.prepare_handle_incoming_blocks(blocks, pblocks))
+ {
+ MERROR("Failed to prepare to add blocks");
+ return 1;
+ }
if (!pblocks.empty() && pblocks.size() != blocks.size())
{
MERROR("Unexpected parsed blocks size");
diff --git a/src/common/combinator.h b/src/common/combinator.h
index 72c6800d5..ba851bd81 100644
--- a/src/common/combinator.h
+++ b/src/common/combinator.h
@@ -32,6 +32,7 @@
#include <iostream>
#include <vector>
+#include <stdexcept>
namespace tools {
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp
index 1a1155c7c..5e03bf897 100644
--- a/src/common/dns_utils.cpp
+++ b/src/common/dns_utils.cpp
@@ -33,7 +33,7 @@
#include <stdlib.h>
#include "include_base_utils.h"
#include "common/threadpool.h"
-#include <random>
+#include "crypto/crypto.h"
#include <boost/thread/mutex.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/optional.hpp>
@@ -517,10 +517,7 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std
std::vector<std::vector<std::string> > records;
records.resize(dns_urls.size());
- std::random_device rd;
- std::mt19937 gen(rd());
- std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
- size_t first_index = dis(gen);
+ size_t first_index = crypto::rand_idx(dns_urls.size());
// send all requests in parallel
std::deque<bool> avail(dns_urls.size(), false), valid(dns_urls.size(), false);
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 22b182ab0..bac456f60 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -35,6 +35,7 @@
#include <boost/optional.hpp>
#include <type_traits>
#include <vector>
+#include <random>
#include "common/pod-class.h"
#include "memwipe.h"
@@ -162,6 +163,32 @@ namespace crypto {
return res;
}
+ /* UniformRandomBitGenerator using crypto::rand<uint64_t>()
+ */
+ struct random_device
+ {
+ typedef uint64_t result_type;
+ static constexpr result_type min() { return 0; }
+ static constexpr result_type max() { return result_type(-1); }
+ result_type operator()() const { return crypto::rand<result_type>(); }
+ };
+
+ /* Generate a random value between range_min and range_max
+ */
+ template<typename T>
+ typename std::enable_if<std::is_integral<T>::value, T>::type rand_range(T range_min, T range_max) {
+ crypto::random_device rd;
+ std::uniform_int_distribution<T> dis(range_min, range_max);
+ return dis(rd);
+ }
+
+ /* Generate a random index between 0 and sz-1
+ */
+ template<typename T>
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type rand_idx(T sz) {
+ return crypto::rand_range<T>(0, sz-1);
+ }
+
/* Generate a new key pair
*/
inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp
index 5162e53e6..859173aa5 100644
--- a/src/cryptonote_basic/difficulty.cpp
+++ b/src/cryptonote_basic/difficulty.cpp
@@ -239,4 +239,19 @@ namespace cryptonote {
return res.convert_to<difficulty_type>();
}
+ std::string hex(difficulty_type v)
+ {
+ static const char chars[] = "0123456789abcdef";
+ std::string s;
+ while (v > 0)
+ {
+ s.push_back(chars[(v & 0xf).convert_to<unsigned>()]);
+ v >>= 4;
+ }
+ if (s.empty())
+ s += "0";
+ std::reverse(s.begin(), s.end());
+ return "0x" + s;
+ }
+
}
diff --git a/src/cryptonote_basic/difficulty.h b/src/cryptonote_basic/difficulty.h
index f7a9376fb..02ed89e5a 100644
--- a/src/cryptonote_basic/difficulty.h
+++ b/src/cryptonote_basic/difficulty.h
@@ -32,6 +32,7 @@
#include <cstdint>
#include <vector>
+#include <string>
#include <boost/multiprecision/cpp_int.hpp>
#include "crypto/hash.h"
@@ -58,4 +59,6 @@ namespace cryptonote
bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty);
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
+
+ std::string hex(difficulty_type v);
}
diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp
index 89bca2f09..61240ea37 100644
--- a/src/cryptonote_basic/hardfork.cpp
+++ b/src/cryptonote_basic/hardfork.cpp
@@ -266,11 +266,9 @@ bool HardFork::reorganize_from_chain_height(uint64_t height)
bool HardFork::rescan_from_block_height(uint64_t height)
{
CRITICAL_REGION_LOCAL(lock);
- db.block_txn_start(true);
- if (height >= db.height()) {
- db.block_txn_stop();
+ db_rtxn_guard rtxn_guard(&db);
+ if (height >= db.height())
return false;
- }
versions.clear();
@@ -293,8 +291,6 @@ bool HardFork::rescan_from_block_height(uint64_t height)
current_fork_index = voted;
}
- db.block_txn_stop();
-
return true;
}
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 7ef8f8c45..51fd9fe16 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -428,6 +428,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
block bl;
block_verification_context bvc = boost::value_initialized<block_verification_context>();
generate_genesis_block(bl, get_config(m_nettype).GENESIS_TX, get_config(m_nettype).GENESIS_NONCE);
+ db_wtxn_guard wtxn_guard(m_db);
add_new_block(bl, bvc);
CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "Failed to add genesis block to blockchain");
}
@@ -443,7 +444,8 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
m_db->fixup();
}
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard(m_db);
+
// check how far behind we are
uint64_t top_block_timestamp = m_db->get_top_block_timestamp();
uint64_t timestamp_diff = time(NULL) - top_block_timestamp;
@@ -464,7 +466,8 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
#endif
MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block());
- m_db->block_txn_stop();
+
+ rtxn_guard.stop();
uint64_t num_popped_blocks = 0;
while (!m_db->is_read_only())
@@ -518,8 +521,11 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
if (test_options && test_options->long_term_block_weight_window)
m_long_term_block_weights_window = test_options->long_term_block_weight_window;
- if (!update_next_cumulative_weight_limit())
- return false;
+ {
+ db_txn_guard txn_guard(m_db, m_db->is_read_only());
+ if (!update_next_cumulative_weight_limit())
+ return false;
+ }
return true;
}
//------------------------------------------------------------------
@@ -725,6 +731,7 @@ bool Blockchain::reset_and_set_genesis_block(const block& b)
m_db->reset();
m_hardfork->init();
+ db_wtxn_guard wtxn_guard(m_db);
block_verification_context bvc = boost::value_initialized<block_verification_context>();
add_new_block(b, bvc);
if (!update_next_cumulative_weight_limit())
@@ -772,7 +779,7 @@ bool Blockchain::get_short_chain_history(std::list<crypto::hash>& ids) const
if(!sz)
return true;
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard(m_db);
bool genesis_included = false;
uint64_t current_back_offset = 1;
while(current_back_offset < sz)
@@ -799,7 +806,6 @@ bool Blockchain::get_short_chain_history(std::list<crypto::hash>& ids) const
{
ids.push_back(m_db->get_block_hash_from_height(0));
}
- m_db->block_txn_stop();
return true;
}
@@ -1866,7 +1872,7 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard (m_db);
rsp.current_blockchain_height = get_current_blockchain_height();
std::vector<std::pair<cryptonote::blobdata,block>> blocks;
get_blocks(arg.blocks, blocks, rsp.missed_ids);
@@ -1893,7 +1899,6 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
// as done below if any standalone transactions were requested
// and missed.
rsp.missed_ids.insert(rsp.missed_ids.end(), missed_tx_ids.begin(), missed_tx_ids.end());
- m_db->block_txn_stop();
return false;
}
@@ -1903,7 +1908,6 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
//get and pack other transactions, if needed
get_transactions_blobs(arg.txs, rsp.txs, rsp.missed_ids);
- m_db->block_txn_stop();
return true;
}
//------------------------------------------------------------------
@@ -2075,14 +2079,13 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
return false;
}
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard(m_db);
// make sure that the last block in the request's block list matches
// the genesis block
auto gen_hash = m_db->get_block_hash_from_height(0);
if(qblock_ids.back() != gen_hash)
{
MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
- m_db->block_txn_abort();
return false;
}
@@ -2100,11 +2103,9 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
catch (const std::exception& e)
{
MWARNING("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
- m_db->block_txn_abort();
return false;
}
}
- m_db->block_txn_stop();
// this should be impossible, as we checked that we share the genesis block,
// but just in case...
@@ -2295,7 +2296,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
return false;
}
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard(m_db);
current_height = get_current_blockchain_height();
const uint32_t pruning_seed = get_blockchain_pruning_seed();
start_height = tools::get_next_unpruned_block_height(start_height, current_height, pruning_seed);
@@ -2307,7 +2308,6 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
hashes.push_back(m_db->get_block_hash_from_height(i));
}
- m_db->block_txn_stop();
return true;
}
@@ -2354,7 +2354,7 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
}
}
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard(m_db);
total_height = get_current_blockchain_height();
size_t count = 0, size = 0;
blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height)));
@@ -2380,7 +2380,6 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
blocks.back().second.push_back(std::make_pair(b.tx_hashes[i], std::move(txs[i])));
}
}
- m_db->block_txn_stop();
return true;
}
//------------------------------------------------------------------
@@ -3535,7 +3534,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
static bool seen_future_version = false;
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard(m_db);
uint64_t blockchain_height;
const crypto::hash top_hash = get_tail_id(blockchain_height);
++blockchain_height; // block height to chain height
@@ -3544,7 +3543,6 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
MERROR_VER("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << top_hash);
bvc.m_verifivation_failed = true;
leave:
- m_db->block_txn_stop();
return false;
}
@@ -3827,7 +3825,7 @@ leave:
if(precomputed)
block_processing_time += m_fake_pow_calc_time;
- m_db->block_txn_stop();
+ rtxn_guard.stop();
TIME_MEASURE_START(addblock);
uint64_t new_height = 0;
if (!bvc.m_verifivation_failed)
@@ -3945,8 +3943,6 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti
LOG_PRINT_L3("Blockchain::" << __func__);
- m_db->block_txn_start(false);
-
// when we reach this, the last hf version is not yet written to the db
const uint64_t db_height = m_db->height();
const uint8_t hf_version = get_current_hard_fork_version();
@@ -3990,7 +3986,6 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti
new_weights[0] = long_term_block_weight;
long_term_median = epee::misc_utils::median(new_weights);
m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
- short_term_constraint = m_long_term_effective_median_block_weight + m_long_term_effective_median_block_weight * 2 / 5;
weights.clear();
get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
@@ -4009,9 +4004,8 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti
if (long_term_effective_median_block_weight)
*long_term_effective_median_block_weight = m_long_term_effective_median_block_weight;
- m_db->add_max_block_size(m_current_block_cumul_weight_limit);
-
- m_db->block_txn_stop();
+ if (!m_db->is_read_only())
+ m_db->add_max_block_size(m_current_block_cumul_weight_limit);
return true;
}
@@ -4022,12 +4016,11 @@ bool Blockchain::add_new_block(const block& bl, block_verification_context& bvc)
crypto::hash id = get_block_hash(bl);
CRITICAL_REGION_LOCAL(m_tx_pool);//to avoid deadlock lets lock tx_pool for whole add/reorganize process
CRITICAL_REGION_LOCAL1(m_blockchain_lock);
- m_db->block_txn_start(true);
+ db_rtxn_guard rtxn_guard(m_db);
if(have_block(id))
{
LOG_PRINT_L3("block with id = " << id << " already exists");
bvc.m_already_exists = true;
- m_db->block_txn_stop();
m_blocks_txs_check.clear();
return false;
}
@@ -4037,14 +4030,14 @@ bool Blockchain::add_new_block(const block& bl, block_verification_context& bvc)
{
//chain switching or wrong block
bvc.m_added_to_main_chain = false;
- m_db->block_txn_stop();
+ rtxn_guard.stop();
bool r = handle_alternative_block(bl, id, bvc);
m_blocks_txs_check.clear();
return r;
//never relay alternative blocks
}
- m_db->block_txn_stop();
+ rtxn_guard.stop();
return handle_block_to_main_chain(bl, id, bvc);
}
//------------------------------------------------------------------
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 91dea4982..be1ea5a17 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1609,6 +1609,9 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::check_fork_time()
{
+ if (m_nettype == FAKECHAIN)
+ return true;
+
HardFork::State state = m_blockchain_storage.get_hard_fork_state();
const el::Level level = el::Level::Warning;
switch (state) {
@@ -1824,7 +1827,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::check_block_rate()
{
- if (m_offline || m_target_blockchain_height > get_current_blockchain_height())
+ if (m_offline || m_nettype == FAKECHAIN || m_target_blockchain_height > get_current_blockchain_height())
{
MDEBUG("Not checking block rate, offline or syncing");
return true;
diff --git a/src/device/device.hpp b/src/device/device.hpp
index 2e485b1d6..866e2c676 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -76,6 +76,7 @@ namespace hw {
class i_device_callback {
public:
virtual void on_button_request(uint64_t code=0) {}
+ virtual void on_button_pressed() {}
virtual boost::optional<epee::wipeable_string> on_pin_request() { return boost::none; }
virtual boost::optional<epee::wipeable_string> on_passphrase_request(bool on_device) { return boost::none; }
virtual void on_progress(const device_progress& event) {}
diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp
index f3d15c5e2..58abde1d1 100644
--- a/src/device_trezor/device_trezor_base.cpp
+++ b/src/device_trezor/device_trezor_base.cpp
@@ -43,7 +43,7 @@ namespace trezor {
const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080};
- device_trezor_base::device_trezor_base(): m_callback(nullptr) {
+ device_trezor_base::device_trezor_base(): m_callback(nullptr), m_last_msg_type(messages::MessageType_Success) {
#ifdef WITH_TREZOR_DEBUGGING
m_debug = false;
#endif
@@ -275,6 +275,12 @@ namespace trezor {
// Later if needed this generic message handler can be replaced by a pointer to
// a protocol message handler which by default points to the device class which implements
// the default handler.
+
+ if (m_last_msg_type == messages::MessageType_ButtonRequest){
+ on_button_pressed();
+ }
+ m_last_msg_type = input.m_type;
+
switch(input.m_type){
case messages::MessageType_ButtonRequest:
on_button_request(input, dynamic_cast<const messages::common::ButtonRequest*>(input.m_msg.get()));
@@ -413,6 +419,11 @@ namespace trezor {
resp = read_raw();
}
+ void device_trezor_base::on_button_pressed()
+ {
+ TREZOR_CALLBACK(on_button_pressed);
+ }
+
void device_trezor_base::on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg)
{
MDEBUG("on_pin_request");
diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp
index 8c3c14b29..c106d2099 100644
--- a/src/device_trezor/device_trezor_base.hpp
+++ b/src/device_trezor/device_trezor_base.hpp
@@ -98,6 +98,7 @@ namespace trezor {
std::shared_ptr<messages::management::Features> m_features; // features from the last device reset
boost::optional<epee::wipeable_string> m_pin;
boost::optional<epee::wipeable_string> m_passphrase;
+ messages::MessageType m_last_msg_type;
cryptonote::network_type network_type;
@@ -311,6 +312,7 @@ namespace trezor {
// Protocol callbacks
void on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg);
+ void on_button_pressed();
void on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg);
void on_passphrase_request(GenericMessage & resp, const messages::common::PassphraseRequest * msg);
void on_passphrase_state_request(GenericMessage & resp, const messages::common::PassphraseStateRequest * msg);
diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp
index 991ba3395..dd9b0b52f 100644
--- a/src/device_trezor/trezor/transport.cpp
+++ b/src/device_trezor/trezor/transport.cpp
@@ -223,6 +223,11 @@ namespace trezor{
msg = msg_wrap;
}
+ static void assert_port_number(uint32_t port)
+ {
+ CHECK_AND_ASSERT_THROW_MES(port >= 1024 && port < 65535, "Invalid port number: " << port);
+ }
+
Transport::Transport(): m_open_counter(0) {
}
@@ -263,6 +268,29 @@ namespace trezor{
const char * BridgeTransport::PATH_PREFIX = "bridge:";
+ BridgeTransport::BridgeTransport(
+ boost::optional<std::string> device_path,
+ boost::optional<std::string> bridge_host):
+ m_device_path(device_path),
+ m_bridge_host(bridge_host ? bridge_host.get() : DEFAULT_BRIDGE),
+ m_response(boost::none),
+ m_session(boost::none),
+ m_device_info(boost::none)
+ {
+ const char *env_bridge_port = nullptr;
+ if (!bridge_host && (env_bridge_port = getenv("TREZOR_BRIDGE_PORT")) != nullptr)
+ {
+ uint16_t bridge_port;
+ CHECK_AND_ASSERT_THROW_MES(epee::string_tools::get_xtype_from_string(bridge_port, env_bridge_port), "Invalid bridge port: " << env_bridge_port);
+ assert_port_number(bridge_port);
+
+ m_bridge_host = std::string("127.0.0.1:") + boost::lexical_cast<std::string>(env_bridge_port);
+ MDEBUG("Bridge host: " << m_bridge_host);
+ }
+
+ m_http_client.set_server(m_bridge_host, boost::none, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
+ }
+
std::string BridgeTransport::get_path() const {
if (!m_device_path){
return "";
@@ -401,28 +429,40 @@ namespace trezor{
const char * UdpTransport::DEFAULT_HOST = "127.0.0.1";
const int UdpTransport::DEFAULT_PORT = 21324;
+ static void parse_udp_path(std::string &host, int &port, std::string path)
+ {
+ if (boost::starts_with(path, UdpTransport::PATH_PREFIX))
+ {
+ path = path.substr(strlen(UdpTransport::PATH_PREFIX));
+ }
+
+ auto delim = path.find(':');
+ if (delim == std::string::npos) {
+ host = path;
+ } else {
+ host = path.substr(0, delim);
+ port = std::stoi(path.substr(delim + 1));
+ }
+ }
+
UdpTransport::UdpTransport(boost::optional<std::string> device_path,
boost::optional<std::shared_ptr<Protocol>> proto) :
m_io_service(), m_deadline(m_io_service)
{
+ m_device_host = DEFAULT_HOST;
m_device_port = DEFAULT_PORT;
+ const char *env_trezor_path = nullptr;
+
if (device_path) {
- const std::string device_str = device_path.get();
- auto delim = device_str.find(':');
- if (delim == std::string::npos) {
- m_device_host = device_str;
- } else {
- m_device_host = device_str.substr(0, delim);
- m_device_port = std::stoi(device_str.substr(delim + 1));
- }
+ parse_udp_path(m_device_host, m_device_port, device_path.get());
+ } else if ((env_trezor_path = getenv("TREZOR_PATH")) != nullptr && boost::starts_with(env_trezor_path, UdpTransport::PATH_PREFIX)){
+ parse_udp_path(m_device_host, m_device_port, std::string(env_trezor_path));
+ MDEBUG("Applied TREZOR_PATH: " << m_device_host << ":" << m_device_port);
} else {
m_device_host = DEFAULT_HOST;
}
- if (m_device_port <= 1024 || m_device_port > 65535){
- throw std::invalid_argument("Port number invalid");
- }
-
+ assert_port_number((uint32_t)m_device_port);
if (m_device_host != "localhost" && m_device_host != DEFAULT_HOST){
throw std::invalid_argument("Local endpoint allowed only");
}
diff --git a/src/device_trezor/trezor/transport.hpp b/src/device_trezor/trezor/transport.hpp
index 2945b3184..cde862547 100644
--- a/src/device_trezor/trezor/transport.hpp
+++ b/src/device_trezor/trezor/transport.hpp
@@ -163,15 +163,7 @@ namespace trezor {
public:
BridgeTransport(
boost::optional<std::string> device_path = boost::none,
- boost::optional<std::string> bridge_host = boost::none):
- m_device_path(device_path),
- m_bridge_host(bridge_host ? bridge_host.get() : DEFAULT_BRIDGE),
- m_response(boost::none),
- m_session(boost::none),
- m_device_info(boost::none)
- {
- m_http_client.set_server(m_bridge_host, boost::none, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
- }
+ boost::optional<std::string> bridge_host = boost::none);
virtual ~BridgeTransport() = default;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index f0aef384f..be97edbe5 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -176,8 +176,15 @@ namespace nodetool
if(!addr.is_blockable())
return false;
+ const time_t now = time(nullptr);
+
CRITICAL_REGION_LOCAL(m_blocked_hosts_lock);
- m_blocked_hosts[addr.host_str()] = time(nullptr) + seconds;
+ time_t limit;
+ if (now > std::numeric_limits<time_t>::max() - seconds)
+ limit = std::numeric_limits<time_t>::max();
+ else
+ limit = now + seconds;
+ m_blocked_hosts[addr.host_str()] = limit;
// drop any connection to that address. This should only have to look into
// the zone related to the connection, but really make sure everything is
@@ -1259,7 +1266,7 @@ namespace nodetool
}
}
else
- random_index = crypto::rand<size_t>() % filtered.size();
+ random_index = crypto::rand_idx(filtered.size());
CHECK_AND_ASSERT_MES(random_index < filtered.size(), false, "random_index < filtered.size() failed!!");
random_index = filtered[random_index];
@@ -1313,7 +1320,7 @@ namespace nodetool
return true;
size_t try_count = 0;
- size_t current_index = crypto::rand<size_t>()%m_seed_nodes.size();
+ size_t current_index = crypto::rand_idx(m_seed_nodes.size());
const net_server& server = m_network_zones.at(epee::net_utils::zone::public_).m_net_server;
while(true)
{
diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h
index ebe0268d8..52814af94 100644
--- a/src/p2p/net_peerlist.h
+++ b/src/p2p/net_peerlist.h
@@ -398,7 +398,7 @@ namespace nodetool
return false;
}
- size_t random_index = crypto::rand<size_t>() % m_peers_gray.size();
+ size_t random_index = crypto::rand_idx(m_peers_gray.size());
peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>();
pe = *epee::misc_utils::move_it_backward(--by_time_index.end(), random_index);
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index e877c13ce..ff2a81d43 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -695,6 +695,7 @@ namespace rct {
CHECK_AND_ASSERT_THROW_MES(mixRing[n].size() == inSk.size(), "Bad mixRing size");
}
CHECK_AND_ASSERT_THROW_MES((kLRki && msout) || (!kLRki && !msout), "Only one of kLRki/msout is present");
+ CHECK_AND_ASSERT_THROW_MES(inSk.size() < 2, "genRct is not suitable for 2+ rings");
rctSig rv;
rv.type = RCTTypeFull;
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index 50d0f4d91..e5413f1dc 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -191,6 +191,8 @@ namespace rct {
Bulletproof(const rct::keyV &V, const rct::key &A, const rct::key &S, const rct::key &T1, const rct::key &T2, const rct::key &taux, const rct::key &mu, const rct::keyV &L, const rct::keyV &R, const rct::key &a, const rct::key &b, const rct::key &t):
V(V), A(A), S(S), T1(T1), T2(T2), taux(taux), mu(mu), L(L), R(R), a(a), b(b), t(t) {}
+ bool operator==(const Bulletproof &other) const { return V == other.V && A == other.A && S == other.S && T1 == other.T1 && T2 == other.T2 && taux == other.taux && mu == other.mu && L == other.L && R == other.R && a == other.a && b == other.b && t == other.t; }
+
BEGIN_SERIALIZE_OBJECT()
// Commitments aren't saved, they're restored via outPk
// FIELD(V)
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 71bfcc950..52d30e526 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -74,7 +74,7 @@ namespace
void store_difficulty(cryptonote::difficulty_type difficulty, uint64_t &sdiff, std::string &swdiff, uint64_t &stop64)
{
sdiff = (difficulty << 64 >> 64).convert_to<uint64_t>();
- swdiff = difficulty.convert_to<std::string>();
+ swdiff = cryptonote::hex(difficulty);
stop64 = (difficulty >> 64).convert_to<uint64_t>();
}
}
@@ -204,6 +204,7 @@ namespace cryptonote
crypto::hash hash;
m_core.get_blockchain_top(res.height, hash);
+ ++res.height; // block height to chain height
res.hash = string_tools::pod_to_hex(hash);
res.status = CORE_RPC_STATUS_OK;
return true;
@@ -1295,7 +1296,10 @@ namespace cryptonote
LOG_ERROR("Failed to find tx pub key in blockblob");
return false;
}
- res.reserved_offset += sizeof(tx_pub_key) + 2; //2 bytes: tag for TX_EXTRA_NONCE(1 byte), counter in TX_EXTRA_NONCE(1 byte)
+ if (req.reserve_size)
+ res.reserved_offset += sizeof(tx_pub_key) + 2; //2 bytes: tag for TX_EXTRA_NONCE(1 byte), counter in TX_EXTRA_NONCE(1 byte)
+ else
+ res.reserved_offset = 0;
if(res.reserved_offset + req.reserve_size > block_blob.size())
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 7bea1374f..8c8afba56 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -3189,10 +3189,11 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("net_stats",
boost::bind(&simple_wallet::net_stats, this, _1),
tr(USAGE_NET_STATS),
+ tr("Prints simple network stats"));
m_cmd_binder.set_handler("welcome",
boost::bind(&simple_wallet::welcome, this, _1),
tr(USAGE_WELCOME),
- tr("Prints simple network stats"));
+ tr("Prints basic info about Monero for first time users"));
m_cmd_binder.set_handler("version",
boost::bind(&simple_wallet::version, this, _1),
tr(USAGE_VERSION),
@@ -5064,8 +5065,7 @@ bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bo
LOCK_IDLE_SCOPE();
crypto::hash transfer_hash_pre{};
- uint64_t height_pre, height_post;
-
+ uint64_t height_pre = 0, height_post;
if (reset != ResetNone)
{
if (reset == ResetSoftKeepKI)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index c1303c225..032b873d6 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -249,6 +249,13 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
}
}
+ virtual void on_device_button_pressed()
+ {
+ if (m_listener) {
+ m_listener->onDeviceButtonPressed();
+ }
+ }
+
virtual boost::optional<epee::wipeable_string> on_device_pin_request()
{
if (m_listener) {
@@ -449,6 +456,11 @@ WalletImpl::~WalletImpl()
close(false); // do not store wallet as part of the closing activities
// Stop refresh thread
stopRefresh();
+
+ if (m_wallet2Callback->getListener()) {
+ m_wallet2Callback->getListener()->onSetWallet(nullptr);
+ }
+
LOG_PRINT_L1(__FUNCTION__ << " finished");
}
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index ee1d6ae79..0af3b1867 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -37,6 +37,7 @@
#include <set>
#include <ctime>
#include <iostream>
+#include <stdexcept>
// Public interface for libwallet library
namespace Monero {
@@ -337,6 +338,7 @@ protected:
bool m_indeterminate;
};
+struct Wallet;
struct WalletListener
{
virtual ~WalletListener() = 0;
@@ -381,7 +383,12 @@ struct WalletListener
/**
* @brief called by device if the action is required
*/
- virtual void onDeviceButtonRequest(uint64_t code) {}
+ virtual void onDeviceButtonRequest(uint64_t code) { (void)code; }
+
+ /**
+ * @brief called by device if the button was pressed
+ */
+ virtual void onDeviceButtonPressed() { }
/**
* @brief called by device when PIN is needed
@@ -401,7 +408,12 @@ struct WalletListener
/**
* @brief Signalizes device operation progress
*/
- virtual void onDeviceProgress(const DeviceProgress & event) {};
+ virtual void onDeviceProgress(const DeviceProgress & event) { (void)event; };
+
+ /**
+ * @brief If the listener is created before the wallet this enables to set created wallet object
+ */
+ virtual void onSetWallet(Wallet * wallet) { (void)wallet; };
};
@@ -440,8 +452,8 @@ struct Wallet
//! returns both error and error string atomically. suggested to use in instead of status() and errorString()
virtual void statusWithErrorString(int& status, std::string& errorString) const = 0;
virtual bool setPassword(const std::string &password) = 0;
- virtual bool setDevicePin(const std::string &password) { return false; };
- virtual bool setDevicePassphrase(const std::string &password) { return false; };
+ virtual bool setDevicePin(const std::string &pin) { (void)pin; return false; };
+ virtual bool setDevicePassphrase(const std::string &passphrase) { (void)passphrase; return false; };
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
std::string mainAddress() const { return address(0, 0); }
virtual std::string path() const = 0;
@@ -1020,9 +1032,10 @@ struct WalletManager
* \param password Password of wallet file
* \param nettype Network type
* \param kdf_rounds Number of rounds for key derivation function
+ * \param listener Wallet listener to set to the wallet after creation
* \return Wallet instance (Wallet::status() needs to be called to check if opened successfully)
*/
- virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1) = 0;
+ virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) = 0;
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
{
return openWallet(path, password, testnet ? TESTNET : MAINNET);
@@ -1134,6 +1147,7 @@ struct WalletManager
* \param restoreHeight restore from start height (0 sets to current height)
* \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value)
* \param kdf_rounds Number of rounds for key derivation function
+ * \param listener Wallet listener to set to the wallet after creation
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * createWalletFromDevice(const std::string &path,
@@ -1142,7 +1156,8 @@ struct WalletManager
const std::string &deviceName,
uint64_t restoreHeight = 0,
const std::string &subaddressLookahead = "",
- uint64_t kdf_rounds = 1) = 0;
+ uint64_t kdf_rounds = 1,
+ WalletListener * listener = nullptr) = 0;
/*!
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index f584e88ac..ef2ed2015 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -57,9 +57,14 @@ Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::stri
return wallet;
}
-Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds)
+Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds, WalletListener * listener)
{
WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
+ wallet->setListener(listener);
+ if (listener){
+ listener->onSetWallet(wallet);
+ }
+
wallet->open(path, password);
//Refresh addressBook
wallet->addressBook()->refresh();
@@ -122,9 +127,15 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
const std::string &deviceName,
uint64_t restoreHeight,
const std::string &subaddressLookahead,
- uint64_t kdf_rounds)
+ uint64_t kdf_rounds,
+ WalletListener * listener)
{
WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
+ wallet->setListener(listener);
+ if (listener){
+ listener->onSetWallet(wallet);
+ }
+
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
} else {
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 0c83d794f..235f96e17 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -40,7 +40,7 @@ class WalletManagerImpl : public WalletManager
public:
Wallet * createWallet(const std::string &path, const std::string &password,
const std::string &language, NetworkType nettype, uint64_t kdf_rounds = 1) override;
- Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1) override;
+ Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) override;
virtual Wallet * recoveryWallet(const std::string &path,
const std::string &password,
const std::string &mnemonic,
@@ -72,7 +72,8 @@ public:
const std::string &deviceName,
uint64_t restoreHeight = 0,
const std::string &subaddressLookahead = "",
- uint64_t kdf_rounds = 1) override;
+ uint64_t kdf_rounds = 1,
+ WalletListener * listener = nullptr) override;
virtual bool closeWallet(Wallet *wallet, bool store = true) override;
bool walletExists(const std::string &path) override;
bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const override;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index dfcc61426..b0e1400fa 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -265,6 +265,7 @@ struct options {
const command_line::arg_descriptor<std::string> hw_device = {"hw-device", tools::wallet2::tr("HW device to use"), ""};
const command_line::arg_descriptor<std::string> hw_device_derivation_path = {"hw-device-deriv-path", tools::wallet2::tr("HW device wallet derivation path (e.g., SLIP-10)"), ""};
const command_line::arg_descriptor<std::string> tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" };
+ const command_line::arg_descriptor<bool> no_dns = {"no-dns", tools::wallet2::tr("Do not use DNS"), false};
};
void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file, std::string &mms_file)
@@ -452,6 +453,9 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
wallet->device_name(device_name);
wallet->device_derivation_path(device_derivation_path);
+ if (command_line::get_arg(vm, opts.no_dns))
+ wallet->enable_dns(false);
+
try
{
if (!command_line::is_arg_defaulted(vm, opts.tx_notify))
@@ -788,7 +792,7 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra
// pseudoOuts
size += 32 * n_inputs;
// ecdhInfo
- size += 2 * 32 * n_outputs;
+ size += 8 * n_outputs;
// outPk - only commitment is saved
size += 32 * n_outputs;
// txnFee
@@ -992,6 +996,12 @@ void wallet_device_callback::on_button_request(uint64_t code)
wallet->on_device_button_request(code);
}
+void wallet_device_callback::on_button_pressed()
+{
+ if (wallet)
+ wallet->on_device_button_pressed();
+}
+
boost::optional<epee::wipeable_string> wallet_device_callback::on_pin_request()
{
if (wallet)
@@ -1072,7 +1082,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_encrypt_keys_after_refresh(boost::none),
m_unattended(unattended),
m_devices_registered(false),
- m_device_last_key_image_sync(0)
+ m_device_last_key_image_sync(0),
+ m_use_dns(true)
{
}
@@ -1127,6 +1138,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.hw_device);
command_line::add_arg(desc_params, opts.hw_device_derivation_path);
command_line::add_arg(desc_params, opts.tx_notify);
+ command_line::add_arg(desc_params, opts.no_dns);
}
std::pair<std::unique_ptr<wallet2>, tools::password_container> wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
@@ -5773,7 +5785,7 @@ namespace
{
CHECK_AND_ASSERT_MES(!vec.empty(), T(), "Vector must be non-empty");
- size_t idx = crypto::rand<size_t>() % vec.size();
+ size_t idx = crypto::rand_idx(vec.size());
return pop_index (vec, idx);
}
@@ -5876,7 +5888,7 @@ size_t wallet2::pop_best_value_from(const transfer_container &transfers, std::ve
}
else
{
- idx = crypto::rand<size_t>() % candidates.size();
+ idx = crypto::rand_idx(candidates.size());
}
return pop_index (unused_indices, candidates[idx]);
}
@@ -7565,7 +7577,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
if (n_rct == 0)
return rct_offsets[block_offset] ? rct_offsets[block_offset] - 1 : 0;
MDEBUG("Picking 1/" << n_rct << " in " << (last_block_offset - first_block_offset + 1) << " blocks centered around " << block_offset + rct_start_height);
- return first_rct + crypto::rand<uint64_t>() % n_rct;
+ return first_rct + crypto::rand_idx(n_rct);
};
size_t num_selected_transfers = 0;
@@ -9621,14 +9633,16 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, s
change -= r.second.first;
MDEBUG("Adding " << cryptonote::print_money(change) << " expected change");
+ // for all txes that have actual change, check change is coming back to the sending wallet
for (const pending_tx &ptx: ptx_vector)
- THROW_WALLET_EXCEPTION_IF(ptx.change_dts.addr != ptx_vector[0].change_dts.addr, error::wallet_internal_error,
- "Change goes to several different addresses");
- const auto it = m_subaddresses.find(ptx_vector[0].change_dts.addr.m_spend_public_key);
- THROW_WALLET_EXCEPTION_IF(change > 0 && it == m_subaddresses.end(), error::wallet_internal_error, "Change address is not ours");
-
- required[ptx_vector[0].change_dts.addr].first += change;
- required[ptx_vector[0].change_dts.addr].second = ptx_vector[0].change_dts.is_subaddress;
+ {
+ if (ptx.change_dts.amount == 0)
+ continue;
+ THROW_WALLET_EXCEPTION_IF(m_subaddresses.find(ptx.change_dts.addr.m_spend_public_key) == m_subaddresses.end(),
+ error::wallet_internal_error, "Change address is not ours");
+ required[ptx.change_dts.addr].first += ptx.change_dts.amount;
+ required[ptx.change_dts.addr].second = ptx.change_dts.is_subaddress;
+ }
for (const auto &r: required)
{
@@ -9694,7 +9708,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
if (unused_transfer_dust_indices_per_subaddr.count(0) == 1 && unused_transfer_dust_indices_per_subaddr.size() > 1)
unused_transfer_dust_indices_per_subaddr.erase(0);
auto i = unused_transfer_dust_indices_per_subaddr.begin();
- std::advance(i, crypto::rand<size_t>() % unused_transfer_dust_indices_per_subaddr.size());
+ std::advance(i, crypto::rand_idx(unused_transfer_dust_indices_per_subaddr.size()));
unused_transfers_indices = i->second.first;
unused_dust_indices = i->second.second;
LOG_PRINT_L2("Spending from subaddress index " << i->first);
@@ -12018,14 +12032,15 @@ void wallet2::import_blockchain(const std::tuple<size_t, crypto::hash, std::vect
m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx);
}
//----------------------------------------------------------------------------------------------------
-std::pair<size_t, std::vector<tools::wallet2::transfer_details>> wallet2::export_outputs() const
+std::pair<size_t, std::vector<tools::wallet2::transfer_details>> wallet2::export_outputs(bool all) const
{
PERF_TIMER(export_outputs);
std::vector<tools::wallet2::transfer_details> outs;
size_t offset = 0;
- while (offset < m_transfers.size() && (m_transfers[offset].m_key_image_known && !m_transfers[offset].m_key_image_request))
- ++offset;
+ if (!all)
+ while (offset < m_transfers.size() && (m_transfers[offset].m_key_image_known && !m_transfers[offset].m_key_image_request))
+ ++offset;
outs.reserve(m_transfers.size() - offset);
for (size_t n = offset; n < m_transfers.size(); ++n)
@@ -12038,13 +12053,13 @@ std::pair<size_t, std::vector<tools::wallet2::transfer_details>> wallet2::export
return std::make_pair(offset, outs);
}
//----------------------------------------------------------------------------------------------------
-std::string wallet2::export_outputs_to_str() const
+std::string wallet2::export_outputs_to_str(bool all) const
{
PERF_TIMER(export_outputs_to_str);
std::stringstream oss;
boost::archive::portable_binary_oarchive ar(oss);
- const auto& outputs = export_outputs();
+ const auto& outputs = export_outputs(all);
ar << outputs;
std::string magic(OUTPUT_EXPORT_FILE_MAGIC, strlen(OUTPUT_EXPORT_FILE_MAGIC));
@@ -12865,8 +12880,7 @@ uint64_t wallet2::get_segregation_fork_height() const
if (m_segregation_height > 0)
return m_segregation_height;
- static const bool use_dns = true;
- if (use_dns)
+ if (m_use_dns)
{
// All four MoneroPulse domains have DNSSEC on and valid
static const std::vector<std::string> dns_urls = {
@@ -12946,6 +12960,12 @@ void wallet2::on_device_button_request(uint64_t code)
m_callback->on_device_button_request(code);
}
//----------------------------------------------------------------------------------------------------
+void wallet2::on_device_button_pressed()
+{
+ if (nullptr != m_callback)
+ m_callback->on_device_button_pressed();
+}
+//----------------------------------------------------------------------------------------------------
boost::optional<epee::wipeable_string> wallet2::on_device_pin_request()
{
if (nullptr != m_callback)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index c8ac7d429..032d2a663 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -105,6 +105,7 @@ namespace tools
virtual void on_lw_money_spent(uint64_t height, const crypto::hash &txid, uint64_t amount) {}
// Device callbacks
virtual void on_device_button_request(uint64_t code) {}
+ virtual void on_device_button_pressed() {}
virtual boost::optional<epee::wipeable_string> on_device_pin_request() { return boost::none; }
virtual boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device) { return boost::none; }
virtual void on_device_progress(const hw::device_progress& event) {};
@@ -118,6 +119,7 @@ namespace tools
public:
wallet_device_callback(wallet2 * wallet): wallet(wallet) {};
void on_button_request(uint64_t code=0) override;
+ void on_button_pressed() override;
boost::optional<epee::wipeable_string> on_pin_request() override;
boost::optional<epee::wipeable_string> on_passphrase_request(bool on_device) override;
void on_progress(const hw::device_progress& event) override;
@@ -1137,8 +1139,8 @@ namespace tools
bool verify_with_public_key(const std::string &data, const crypto::public_key &public_key, const std::string &signature) const;
// Import/Export wallet data
- std::pair<size_t, std::vector<tools::wallet2::transfer_details>> export_outputs() const;
- std::string export_outputs_to_str() const;
+ std::pair<size_t, std::vector<tools::wallet2::transfer_details>> export_outputs(bool all = false) const;
+ std::string export_outputs_to_str(bool all = false) const;
size_t import_outputs(const std::pair<size_t, std::vector<tools::wallet2::transfer_details>> &outputs);
size_t import_outputs_from_str(const std::string &outputs_st);
payment_container export_payments() const;
@@ -1288,6 +1290,7 @@ namespace tools
void hash_m_transfer(const transfer_details & transfer, crypto::hash &hash) const;
uint64_t hash_m_transfers(int64_t transfer_height, crypto::hash &hash) const;
void finish_rescan_bc_keep_key_images(uint64_t transfer_height, const crypto::hash &hash);
+ void enable_dns(bool enable) { m_use_dns = enable; }
private:
/*!
@@ -1378,6 +1381,7 @@ namespace tools
wallet_device_callback * get_device_callback();
void on_device_button_request(uint64_t code);
+ void on_device_button_pressed();
boost::optional<epee::wipeable_string> on_device_pin_request();
boost::optional<epee::wipeable_string> on_device_passphrase_request(bool on_device);
void on_device_progress(const hw::device_progress& event);
@@ -1469,6 +1473,7 @@ namespace tools
std::string m_device_name;
std::string m_device_derivation_path;
uint64_t m_device_last_key_image_sync;
+ bool m_use_dns;
// Aux transaction data from device
std::unordered_map<crypto::hash, std::string> m_tx_device;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 71c64d3c1..24981980c 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -2581,7 +2581,7 @@ namespace tools
try
{
- res.outputs_data_hex = epee::string_tools::buff_to_hex_nodelimer(m_wallet->export_outputs_to_str());
+ res.outputs_data_hex = epee::string_tools::buff_to_hex_nodelimer(m_wallet->export_outputs_to_str(req.all));
}
catch (const std::exception &e)
{
@@ -3111,6 +3111,18 @@ namespace tools
er.message = "Invalid filename";
return false;
}
+ if (m_wallet && req.autosave_current)
+ {
+ try
+ {
+ m_wallet->store();
+ }
+ catch (const std::exception& e)
+ {
+ handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+ return false;
+ }
+ }
std::string wallet_file = m_wallet_dir + "/" + req.filename;
{
po::options_description desc("dummy");
@@ -3141,18 +3153,7 @@ namespace tools
}
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();
return true;
}
@@ -3161,14 +3162,17 @@ namespace tools
{
if (!m_wallet) return not_open(er);
- try
- {
- m_wallet->store();
- }
- catch (const std::exception& e)
+ if (req.autosave_current)
{
- handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
- return false;
+ 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 = NULL;
@@ -3385,6 +3389,20 @@ namespace tools
return false;
}
+ if (m_wallet && req.autosave_current)
+ {
+ try
+ {
+ if (!wallet_file.empty())
+ m_wallet->store();
+ }
+ catch (const std::exception &e)
+ {
+ handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+ return false;
+ }
+ }
+
try
{
if (!req.spendkey.empty())
@@ -3433,19 +3451,7 @@ namespace tools
}
if (m_wallet)
- {
- try
- {
- if (!wallet_file.empty())
- 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;
@@ -3511,6 +3517,18 @@ namespace tools
return false;
}
}
+ if (m_wallet && req.autosave_current)
+ {
+ try
+ {
+ m_wallet->store();
+ }
+ catch (const std::exception &e)
+ {
+ handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
+ return false;
+ }
+ }
// process seed_offset if given
{
@@ -3621,18 +3639,7 @@ namespace tools
}
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());
res.info = "Wallet has been restored successfully.";
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index bb360ae01..8757acef2 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -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 9
+#define WALLET_RPC_VERSION_MINOR 10
#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
@@ -1626,7 +1626,10 @@ namespace wallet_rpc
{
struct request_t
{
+ bool all;
+
BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(all)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -2043,10 +2046,12 @@ namespace wallet_rpc
{
std::string filename;
std::string password;
+ bool autosave_current;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(filename)
KV_SERIALIZE(password)
+ KV_SERIALIZE_OPT(autosave_current, true)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -2063,7 +2068,10 @@ namespace wallet_rpc
{
struct request_t
{
+ bool autosave_current;
+
BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE_OPT(autosave_current, true)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -2108,6 +2116,7 @@ namespace wallet_rpc
std::string spendkey;
std::string viewkey;
std::string password;
+ bool autosave_current;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
@@ -2116,6 +2125,7 @@ namespace wallet_rpc
KV_SERIALIZE(spendkey)
KV_SERIALIZE(viewkey)
KV_SERIALIZE(password)
+ KV_SERIALIZE_OPT(autosave_current, true)
END_KV_SERIALIZE_MAP()
};
@@ -2141,6 +2151,7 @@ namespace wallet_rpc
std::string seed_offset;
std::string password;
std::string language;
+ bool autosave_current;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
@@ -2149,6 +2160,7 @@ namespace wallet_rpc
KV_SERIALIZE(seed_offset)
KV_SERIALIZE(password)
KV_SERIALIZE(language)
+ KV_SERIALIZE_OPT(autosave_current, true)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;