aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cryptonote_core/blockchain.cpp13
-rw-r--r--src/cryptonote_core/miner.cpp5
-rw-r--r--src/p2p/net_peerlist.h4
-rw-r--r--src/simplewallet/simplewallet.cpp39
-rw-r--r--src/simplewallet/simplewallet.h2
-rw-r--r--src/wallet/wallet2.cpp57
-rw-r--r--src/wallet/wallet2.h3
-rw-r--r--src/wallet/wallet_rpc_server.cpp23
-rw-r--r--src/wallet/wallet_rpc_server.h2
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h15
-rw-r--r--tests/core_tests/chaingen.h4
-rw-r--r--tests/unit_tests/hardfork.cpp2
12 files changed, 131 insertions, 38 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 141a42f49..e4d3d57fc 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -2078,6 +2078,7 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
boost::asio::io_service ioservice;
boost::thread_group threadpool;
+ bool ioservice_active = false;
std::unique_ptr < boost::asio::io_service::work > work(new boost::asio::io_service::work(ioservice));
if(threads > 1)
@@ -2086,15 +2087,19 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
{
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
}
+ ioservice_active = true;
}
#define KILL_IOSERVICE() \
- if(threads > 1) \
+ if(ioservice_active) \
{ \
work.reset(); \
threadpool.join_all(); \
ioservice.stop(); \
- } \
+ ioservice_active = false; \
+ }
+
+ epee::misc_utils::auto_scope_leave_caller ioservice_killer = epee::misc_utils::create_scope_leave_handler([&]() { KILL_IOSERVICE(); });
for (const auto& txin : tx.vin)
{
@@ -2109,7 +2114,6 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
if(have_tx_keyimg_as_spent(in_to_key.k_image))
{
LOG_PRINT_L1("Key image already spent in blockchain: " << epee::string_tools::pod_to_hex(in_to_key.k_image));
- KILL_IOSERVICE();
return false;
}
@@ -2123,7 +2127,6 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
if(!itk->second)
{
LOG_PRINT_L1("Failed ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
- KILL_IOSERVICE();
return false;
}
@@ -2145,7 +2148,6 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
LOG_PRINT_L1(" *pmax_used_block_height: " << *pmax_used_block_height);
}
- KILL_IOSERVICE();
return false;
}
@@ -2168,7 +2170,6 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
LOG_PRINT_L1("*pmax_used_block_height: " << *pmax_used_block_height);
}
- KILL_IOSERVICE();
return false;
}
it->second[in_to_key.k_image] = true;
diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp
index 00a474524..5fde94752 100644
--- a/src/cryptonote_core/miner.cpp
+++ b/src/cryptonote_core/miner.cpp
@@ -278,14 +278,17 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------------
bool miner::stop()
{
+ if (!is_mining())
+ return true;
+
send_stop_signal();
CRITICAL_REGION_LOCAL(m_threads_lock);
BOOST_FOREACH(boost::thread& th, m_threads)
th.join();
- m_threads.clear();
LOG_PRINT_L0("Mining has been stopped, " << m_threads.size() << " finished" );
+ m_threads.clear();
return true;
}
//-----------------------------------------------------------------------------------------------------
diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h
index 3d8b08ce6..03f508195 100644
--- a/src/p2p/net_peerlist.h
+++ b/src/p2p/net_peerlist.h
@@ -80,8 +80,6 @@ namespace nodetool
bool set_peer_just_seen(peerid_type peer, const net_address& addr);
bool set_peer_unreachable(const peerlist_entry& pr);
bool is_ip_allowed(uint32_t ip);
- void trim_white_peerlist();
- void trim_gray_peerlist();
private:
@@ -166,6 +164,8 @@ namespace nodetool
private:
bool peers_indexed_from_old(const peers_indexed_old& pio, peers_indexed& pi);
+ void trim_white_peerlist();
+ void trim_gray_peerlist();
friend class boost::serialization::access;
epee::critical_section m_peerlist_lock;
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index ad4cd5622..b8586bf17 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -551,6 +551,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("get_tx_key", boost::bind(&simple_wallet::get_tx_key, this, _1), tr("Get transaction key (r) for a given <txid>"));
m_cmd_binder.set_handler("check_tx_key", boost::bind(&simple_wallet::check_tx_key, this, _1), tr("Check amount going to <address> in <txid>"));
m_cmd_binder.set_handler("show_transfers", boost::bind(&simple_wallet::show_transfers, this, _1), tr("show_transfers [in|out] [<min_height> [<max_height>]] - Show incoming/outgoing transfers within an optional height range"));
+ m_cmd_binder.set_handler("rescan_bc", boost::bind(&simple_wallet::rescan_blockchain, this, _1), tr("Rescan blockchain from scratch"));
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help"));
}
//----------------------------------------------------------------------------------------------------
@@ -1324,7 +1325,7 @@ void simple_wallet::on_skip_transaction(uint64_t height, const cryptonote::trans
m_refresh_progress_reporter.update(height, true);
}
//----------------------------------------------------------------------------------------------------
-bool simple_wallet::refresh(const std::vector<std::string>& args)
+bool simple_wallet::refresh_main(uint64_t start_height, bool reset)
{
if (!try_connect_to_daemon())
return true;
@@ -1336,21 +1337,12 @@ bool simple_wallet::refresh(const std::vector<std::string>& args)
std::unique_lock<std::mutex> lock(m_auto_refresh_mutex);
m_auto_refresh_cond.notify_one();
+ if (reset)
+ m_wallet->rescan_blockchain(false);
+
message_writer() << tr("Starting refresh...");
uint64_t fetched_blocks = 0;
- uint64_t start_height = 0;
- if(!args.empty()){
- try
- {
- start_height = boost::lexical_cast<uint64_t>( args[0] );
- }
- catch(const boost::bad_lexical_cast &)
- {
- start_height = 0;
- }
- }
-
bool ok = false;
std::ostringstream ss;
try
@@ -1408,6 +1400,22 @@ bool simple_wallet::refresh(const std::vector<std::string>& args)
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::refresh(const std::vector<std::string>& args)
+{
+ uint64_t start_height = 0;
+ if(!args.empty()){
+ try
+ {
+ start_height = boost::lexical_cast<uint64_t>( args[0] );
+ }
+ catch(const boost::bad_lexical_cast &)
+ {
+ start_height = 0;
+ }
+ }
+ return refresh_main(start_height, false);
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::show_balance(const std::vector<std::string>& args/* = std::vector<std::string>()*/)
{
success_msg_writer() << tr("Balance: ") << print_money(m_wallet->balance()) << ", "
@@ -2276,6 +2284,11 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::rescan_blockchain(const std::vector<std::string> &args_)
+{
+ return refresh_main(0, true);
+}
+//----------------------------------------------------------------------------------------------------
void simple_wallet::wallet_refresh_thread()
{
while (true)
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index ef44d5374..486e197ae 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -132,6 +132,8 @@ namespace cryptonote
bool get_tx_key(const std::vector<std::string> &args);
bool check_tx_key(const std::vector<std::string> &args);
bool show_transfers(const std::vector<std::string> &args);
+ bool rescan_blockchain(const std::vector<std::string> &args);
+ bool refresh_main(uint64_t start_height, bool reset = false);
uint64_t get_daemon_blockchain_height(std::string& err);
bool try_connect_to_daemon();
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index cfa33b283..e58629dac 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -648,21 +648,30 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched)
refresh(start_height, blocks_fetched, received_money);
}
//----------------------------------------------------------------------------------------------------
-void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks)
+void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks, bool &error)
{
- // prepend the last 3 blocks, should be enough to guard against a block or two's reorg
- cryptonote::block bl;
- std::list<cryptonote::block_complete_entry>::const_reverse_iterator i = prev_blocks.rbegin();
- for (size_t n = 0; n < std::min((size_t)3, prev_blocks.size()); ++n)
+ error = false;
+
+ try
{
- bool ok = cryptonote::parse_and_validate_block_from_blob(i->block, bl);
- THROW_WALLET_EXCEPTION_IF(!ok, error::block_parse_error, i->block);
- short_chain_history.push_front(cryptonote::get_block_hash(bl));
- ++i;
- }
+ // prepend the last 3 blocks, should be enough to guard against a block or two's reorg
+ cryptonote::block bl;
+ std::list<cryptonote::block_complete_entry>::const_reverse_iterator i = prev_blocks.rbegin();
+ for (size_t n = 0; n < std::min((size_t)3, prev_blocks.size()); ++n)
+ {
+ bool ok = cryptonote::parse_and_validate_block_from_blob(i->block, bl);
+ THROW_WALLET_EXCEPTION_IF(!ok, error::block_parse_error, i->block);
+ short_chain_history.push_front(cryptonote::get_block_hash(bl));
+ ++i;
+ }
- // pull the new blocks
- pull_blocks(start_height, blocks_start_height, short_chain_history, blocks);
+ // pull the new blocks
+ pull_blocks(start_height, blocks_start_height, short_chain_history, blocks);
+ }
+ catch(...)
+ {
+ error = true;
+ }
}
//----------------------------------------------------------------------------------------------------
void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& received_money)
@@ -689,7 +698,8 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
// pull the next set of blocks while we're processing the current one
uint64_t next_blocks_start_height;
std::list<cryptonote::block_complete_entry> next_blocks;
- pull_thread = std::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks);});
+ bool error = false;
+ pull_thread = std::thread([&]{pull_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks, next_blocks, error);});
process_blocks(blocks_start_height, blocks, added_blocks);
blocks_fetched += added_blocks;
@@ -700,6 +710,12 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
// switch to the new blocks from the daemon
blocks_start_height = next_blocks_start_height;
blocks = next_blocks;
+
+ // handle error from async fetching thread
+ if (error)
+ {
+ throw std::runtime_error("proxy exception in refresh thread");
+ }
}
catch (const std::exception&)
{
@@ -785,6 +801,7 @@ bool wallet2::clear()
{
m_blockchain.clear();
m_transfers.clear();
+ m_key_images.clear();
m_local_bc_height = 1;
return true;
}
@@ -1415,6 +1432,20 @@ void wallet2::rescan_spent()
}
}
//----------------------------------------------------------------------------------------------------
+void wallet2::rescan_blockchain(bool refresh)
+{
+ clear();
+
+ cryptonote::block genesis;
+ generate_genesis(genesis);
+ crypto::hash genesis_hash = get_block_hash(genesis);
+ m_blockchain.push_back(genesis_hash);
+ m_local_bc_height = 1;
+
+ if (refresh)
+ this->refresh();
+}
+//----------------------------------------------------------------------------------------------------
bool wallet2::is_transfer_unlocked(const transfer_details& td) const
{
if(!is_tx_spendtime_unlocked(td.m_tx.unlock_time))
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index adb7b13e2..88a5268bc 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -280,6 +280,7 @@ namespace tools
void get_unconfirmed_payments_out(std::list<std::pair<crypto::hash,wallet2::unconfirmed_transfer_details>>& unconfirmed_payments) const;
uint64_t get_blockchain_current_height() const { return m_local_bc_height; }
void rescan_spent();
+ void rescan_blockchain(bool refresh = true);
template <class t_archive>
inline void serialize(t_archive &a, const unsigned int ver)
{
@@ -359,7 +360,7 @@ namespace tools
bool is_transfer_unlocked(const transfer_details& td) const;
bool clear();
void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::list<cryptonote::block_complete_entry> &blocks);
- void pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks);
+ void pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, const std::list<cryptonote::block_complete_entry> &prev_blocks, std::list<cryptonote::block_complete_entry> &blocks, bool &error);
void process_blocks(uint64_t start_height, const std::list<cryptonote::block_complete_entry> &blocks, uint64_t& blocks_added);
uint64_t select_transfers(uint64_t needed_money, bool add_dust, uint64_t dust, std::list<transfer_container::iterator>& selected_transfers);
bool prepare_file_names(const std::string& file_path);
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 0c1ea48c1..9f23908f9 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -646,6 +646,29 @@ namespace tools
return true;
}
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_rescan_blockchain(const wallet_rpc::COMMAND_RPC_RESCAN_BLOCKCHAIN::request& req, wallet_rpc::COMMAND_RPC_RESCAN_BLOCKCHAIN::response& res, epee::json_rpc::error& er)
+ {
+ if (m_wallet.restricted())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_DENIED;
+ er.message = "Command unavailable in restricted mode.";
+ return false;
+ }
+
+ try
+ {
+ m_wallet.rescan_blockchain();
+ }
+ catch (std::exception& e)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = e.what();
+ return false;
+ }
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_stop_wallet(const wallet_rpc::COMMAND_RPC_STOP_WALLET::request& req, wallet_rpc::COMMAND_RPC_STOP_WALLET::response& res, epee::json_rpc::error& er)
{
if (m_wallet.restricted())
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index 97b84fcb6..fbc2c29c2 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -75,6 +75,7 @@ namespace tools
MAP_JON_RPC_WE("make_integrated_address", on_make_integrated_address, wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS)
MAP_JON_RPC_WE("split_integrated_address", on_split_integrated_address, wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS)
MAP_JON_RPC_WE("stop_wallet", on_stop_wallet, wallet_rpc::COMMAND_RPC_STOP_WALLET)
+ MAP_JON_RPC_WE("rescan_blockchain", on_rescan_blockchain, wallet_rpc::COMMAND_RPC_RESCAN_BLOCKCHAIN)
END_JSON_RPC_MAP()
END_URI_MAP2()
@@ -93,6 +94,7 @@ namespace tools
bool on_get_bulk_payments(const wallet_rpc::COMMAND_RPC_GET_BULK_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_BULK_PAYMENTS::response& res, epee::json_rpc::error& er);
bool on_incoming_transfers(const wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::response& res, epee::json_rpc::error& er);
bool on_stop_wallet(const wallet_rpc::COMMAND_RPC_STOP_WALLET::request& req, wallet_rpc::COMMAND_RPC_STOP_WALLET::response& res, epee::json_rpc::error& er);
+ bool on_rescan_blockchain(const wallet_rpc::COMMAND_RPC_RESCAN_BLOCKCHAIN::request& req, wallet_rpc::COMMAND_RPC_RESCAN_BLOCKCHAIN::response& res, epee::json_rpc::error& er);
bool handle_command_line(const boost::program_options::variables_map& vm);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index a20c8b969..1e1482c1a 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -391,6 +391,21 @@ namespace wallet_rpc
};
};
+ struct COMMAND_RPC_RESCAN_BLOCKCHAIN
+ {
+ struct request
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
}
}
diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h
index 822ccfb11..17b78da8e 100644
--- a/tests/core_tests/chaingen.h
+++ b/tests/core_tests/chaingen.h
@@ -498,7 +498,9 @@ inline bool do_replay_events(std::vector<test_event_entry>& events)
return false;
}
t_test_class validator;
- return replay_events_through_core<t_test_class>(c, events, validator);
+ bool ret = replay_events_through_core<t_test_class>(c, events, validator);
+ c.deinit();
+ return ret;
}
//--------------------------------------------------------------------------
template<class t_test_class>
diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp
index 82b1a33ff..899f216fd 100644
--- a/tests/unit_tests/hardfork.cpp
+++ b/tests/unit_tests/hardfork.cpp
@@ -102,6 +102,7 @@ public:
virtual bool for_all_blocks(std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const { return true; }
virtual bool for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)>) const { return true; }
virtual bool for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, size_t tx_idx)> f) const { return true; }
+ virtual bool is_read_only() const { return false; }
virtual void add_block( const block& blk
, const size_t& block_size
@@ -282,7 +283,6 @@ TEST(reorganize, Same)
TEST(reorganize, Changed)
{
- int history = 4;
TestDB db;
HardFork hf(db, 1, 0, 1, 1, 4, 100);