aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt16
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.h28
-rw-r--r--src/blockchain_db/blockchain_db.h26
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp498
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h12
-rw-r--r--src/blocks/blockexports.c16
-rw-r--r--src/common/dns_utils.cpp77
-rw-r--r--src/crypto/aesb.c134
-rw-r--r--src/crypto/slow-hash.c190
-rw-r--r--src/cryptonote_core/CMakeLists.txt6
-rw-r--r--src/cryptonote_core/blockchain.cpp4542
-rw-r--r--src/cryptonote_core/blockchain.h64
-rw-r--r--src/cryptonote_core/blockchain_storage.cpp90
-rw-r--r--src/cryptonote_core/checkpoints_create.cpp76
-rw-r--r--src/cryptonote_core/cryptonote_basic_impl.cpp18
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp62
-rw-r--r--src/cryptonote_core/cryptonote_core.h18
-rw-r--r--src/cryptonote_core/difficulty.cpp82
-rw-r--r--src/cryptonote_core/miner.cpp29
-rw-r--r--src/cryptonote_core/tx_pool.cpp24
-rw-r--r--src/cryptonote_core/tx_pool.h16
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl555
-rw-r--r--src/daemon/CMakeLists.txt12
-rw-r--r--src/daemon/main.cpp22
-rw-r--r--src/p2p/net_node.h66
-rw-r--r--src/p2p/net_node.inl406
-rw-r--r--src/wallet/wallet2.cpp15
-rw-r--r--src/wallet/wallet_errors.h6
28 files changed, 3571 insertions, 3535 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 34c52919e..c3fecadae 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,21 +1,21 @@
# Copyright (c) 2014-2015, The Monero Project
-#
+#
# All rights reserved.
-#
+#
# Redistribution and use in source and binary forms, with or without modification, are
# permitted provided that the following conditions are met:
-#
+#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
-#
+#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other
# materials provided with the distribution.
-#
+#
# 3. Neither the name of the copyright holder nor the names of its contributors may be
# used to endorse or promote products derived from this software without specific
# prior written permission.
-#
+#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
+#
# Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
if (WIN32 OR STATIC)
@@ -105,5 +105,5 @@ add_subdirectory(daemon)
add_subdirectory(blockchain_utilities)
if(PER_BLOCK_CHECKPOINT)
- add_subdirectory(blocks)
+ add_subdirectory(blocks)
endif()
diff --git a/src/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h
index c79d8b26f..ce3da91e8 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.h
+++ b/src/blockchain_db/berkeleydb/db_bdb.h
@@ -1,20 +1,20 @@
// Copyright (c) 2014, The Monero Project
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -99,18 +99,18 @@ private:
template <typename T>
class bdb_safe_buffer
{
- // limit the number of buffers to 8
- const size_t MaxAllowedBuffers = 8;
+ // limit the number of buffers to 8
+ const size_t MaxAllowedBuffers = 8;
public:
bdb_safe_buffer(size_t num_buffers, size_t count)
{
- if(num_buffers > MaxAllowedBuffers)
- num_buffers = MaxAllowedBuffers;
-
- set_count(num_buffers);
- for (size_t i = 0; i < num_buffers; i++)
- m_buffers.push_back((T) malloc(sizeof(T) * count));
- m_buffer_count = count;
+ if(num_buffers > MaxAllowedBuffers)
+ num_buffers = MaxAllowedBuffers;
+
+ set_count(num_buffers);
+ for (size_t i = 0; i < num_buffers; i++)
+ m_buffers.push_back((T) malloc(sizeof(T) * count));
+ m_buffer_count = count;
}
~bdb_safe_buffer()
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 193a34386..702de18b5 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1,21 +1,21 @@
// Copyright (c) 2014, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -85,7 +85,7 @@
* size_t get_block_size(height)
* difficulty get_block_cumulative_difficulty(height)
* uint64_t get_block_already_generated_coins(height)
- * uint64_t get_block_timestamp(height)
+ * uint64_t get_block_timestamp(height)
* uint64_t get_top_block_timestamp()
* hash get_block_hash_from_height(height)
* blocks get_blocks_range(height1, height2)
@@ -139,12 +139,12 @@ typedef std::pair<crypto::hash, uint64_t> tx_out_index;
#pragma pack(push, 1)
struct output_data_t
{
- crypto::public_key pubkey;
- uint64_t unlock_time;
- uint64_t height;
+ crypto::public_key pubkey;
+ uint64_t unlock_time;
+ uint64_t height;
};
#pragma pack(pop)
-
+
/***********************************
* Exception Definitions
***********************************/
@@ -300,7 +300,7 @@ private:
/*********************************************************************
* private concrete members
- *********************************************************************/
+ *********************************************************************/
// private version of pop_block, for undoing if an add_block goes tits up
void pop_block();
@@ -479,7 +479,7 @@ public:
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) = 0;
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices) = 0;
virtual void get_output_key(const uint64_t &amount, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs) = 0;
-
+
virtual bool can_thread_bulk_indices() const = 0;
// return a vector of indices corresponding to the global output index for
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index f76fee87a..4a4550179 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -1,20 +1,20 @@
// Copyright (c) 2014, The Monero Project
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -72,19 +72,19 @@ struct lmdb_cur
done = false;
}
- ~lmdb_cur()
- {
- close();
- }
+ ~lmdb_cur()
+ {
+ close();
+ }
- operator MDB_cursor*()
- {
- return m_cur;
- }
- operator MDB_cursor**()
- {
- return &m_cur;
- }
+ operator MDB_cursor*()
+ {
+ return m_cur;
+ }
+ operator MDB_cursor**()
+ {
+ return &m_cur;
+ }
void close()
{
@@ -103,8 +103,8 @@ private:
template<typename T>
struct MDB_val_copy: public MDB_val
{
- MDB_val_copy(const T &t) :
- t_copy(t)
+ MDB_val_copy(const T &t) :
+ t_copy(t)
{
mv_size = sizeof (T);
mv_data = &t_copy;
@@ -116,8 +116,8 @@ private:
template<>
struct MDB_val_copy<cryptonote::blobdata>: public MDB_val
{
- MDB_val_copy(const cryptonote::blobdata &bd) :
- data(new char[bd.size()])
+ MDB_val_copy(const cryptonote::blobdata &bd) :
+ data(new char[bd.size()])
{
memcpy(data.get(), bd.data(), bd.size());
mv_size = bd.size();
@@ -130,8 +130,8 @@ private:
template<>
struct MDB_val_copy<const char*>: public MDB_val
{
- MDB_val_copy(const char *s) :
- data(strdup(s))
+ MDB_val_copy(const char *s) :
+ data(strdup(s))
{
mv_size = strlen(s) + 1; // include the NUL, makes it easier for compares
mv_data = data.get();
@@ -160,16 +160,16 @@ auto compare_uint8 = [](const MDB_val *a, const MDB_val *b)
int compare_hash32(const MDB_val *a, const MDB_val *b)
{
- uint32_t *va = (uint32_t*) a->mv_data;
- uint32_t *vb = (uint32_t*) b->mv_data;
- for (int n = 7; n >= 0; n--)
- {
- if (va[n] == vb[n])
- continue;
- return va[n] < vb[n] ? -1 : 1;
- }
+ uint32_t *va = (uint32_t*) a->mv_data;
+ uint32_t *vb = (uint32_t*) b->mv_data;
+ for (int n = 7; n >= 0; n--)
+ {
+ if (va[n] == vb[n])
+ continue;
+ return va[n] < vb[n] ? -1 : 1;
+ }
- return 0;
+ return 0;
}
int compare_string(const MDB_val *a, const MDB_val *b)
@@ -313,18 +313,18 @@ void BlockchainLMDB::do_resize(uint64_t increase_size)
// check disk capacity
try
{
- boost::filesystem::path path(m_folder);
- boost::filesystem::space_info si = boost::filesystem::space(path);
- if(si.available < add_size)
- {
- LOG_PRINT_RED_L0("!! WARNING: Insufficient free space to extend database !!: " << si.available / 1LL << 20L);
- return;
- }
+ boost::filesystem::path path(m_folder);
+ boost::filesystem::space_info si = boost::filesystem::space(path);
+ if(si.available < add_size)
+ {
+ LOG_PRINT_RED_L0("!! WARNING: Insufficient free space to extend database !!: " << si.available / 1LL << 20L);
+ return;
+ }
}
catch(...)
{
- // print something but proceed.
- LOG_PRINT_YELLOW("Unable to query free disk space.", LOG_LEVEL_0);
+ // print something but proceed.
+ LOG_PRINT_YELLOW("Unable to query free disk space.", LOG_LEVEL_0);
}
MDB_envinfo mei;
@@ -417,7 +417,7 @@ bool BlockchainLMDB::need_resize(uint64_t threshold_size) const
}
return false;
#else
- return false;
+ return false;
#endif
}
@@ -505,7 +505,7 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks) con
}
void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
- const crypto::hash& blk_hash)
+ const crypto::hash& blk_hash)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -685,15 +685,15 @@ void BlockchainLMDB::add_output(const crypto::hash& tx_hash, const tx_out& tx_ou
if (tx_output.target.type() == typeid(txout_to_key))
{
- output_data_t od;
- od.pubkey = boost::get < txout_to_key > (tx_output.target).key;
- od.unlock_time = unlock_time;
- od.height = m_height;
+ output_data_t od;
+ od.pubkey = boost::get < txout_to_key > (tx_output.target).key;
+ od.unlock_time = unlock_time;
+ od.height = m_height;
- MDB_val_copy<output_data_t> data(od);
- //MDB_val_copy<crypto::public_key> val_pubkey(boost::get<txout_to_key>(tx_output.target).key);
- if (mdb_put(*m_write_txn, m_output_keys, &k, &data, 0))
- throw0(DB_ERROR("Failed to add output pubkey to db transaction"));
+ MDB_val_copy<output_data_t> data(od);
+ //MDB_val_copy<crypto::public_key> val_pubkey(boost::get<txout_to_key>(tx_output.target).key);
+ if (mdb_put(*m_write_txn, m_output_keys, &k, &data, 0))
+ throw0(DB_ERROR("Failed to add output pubkey to db transaction"));
}
m_num_outputs++;
@@ -891,17 +891,17 @@ tx_out BlockchainLMDB::output_from_blob(const blobdata& blob) const
return o;
}
-uint64_t BlockchainLMDB::get_output_global_index(const uint64_t& amount, const uint64_t& index)
+uint64_t BlockchainLMDB::get_output_global_index(const uint64_t& amount, const uint64_t& index)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- std::vector <uint64_t> offsets;
- std::vector <uint64_t> global_indices;
- offsets.push_back(index);
- get_output_global_indices(amount, offsets, global_indices);
- if (!global_indices.size())
+ std::vector <uint64_t> offsets;
+ std::vector <uint64_t> global_indices;
+ offsets.push_back(index);
+ get_output_global_indices(amount, offsets, global_indices);
+ if (!global_indices.size())
throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
- return global_indices[0];
+ return global_indices[0];
}
void BlockchainLMDB::check_open() const
@@ -956,7 +956,7 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
// check for existing LMDB files in base directory
boost::filesystem::path old_files = direc.parent_path();
- if (boost::filesystem::exists(old_files / "data.mdb") || boost::filesystem::exists(old_files / "lock.mdb"))
+ if (boost::filesystem::exists(old_files / "data.mdb") || boost::filesystem::exists(old_files / "lock.mdb"))
{
LOG_PRINT_L0("Found existing LMDB files in " << old_files.string());
LOG_PRINT_L0("Move data.mdb and/or lock.mdb to " << filename << ", or delete them, and then restart");
@@ -1022,7 +1022,7 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
lmdb_db_open(txn, LMDB_OUTPUT_TXS, MDB_INTEGERKEY | MDB_CREATE, m_output_txs, "Failed to open db handle for m_output_txs");
lmdb_db_open(txn, LMDB_OUTPUT_INDICES, MDB_INTEGERKEY | MDB_CREATE, m_output_indices, "Failed to open db handle for m_output_indices");
- lmdb_db_open(txn, LMDB_OUTPUT_AMOUNTS, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_output_amounts, "Failed to open db handle for m_output_amounts");
+ lmdb_db_open(txn, LMDB_OUTPUT_AMOUNTS, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_output_amounts, "Failed to open db handle for m_output_amounts");
lmdb_db_open(txn, LMDB_OUTPUT_KEYS, MDB_INTEGERKEY | MDB_CREATE, m_output_keys, "Failed to open db handle for m_output_keys");
lmdb_db_open(txn, LMDB_SPENT_KEYS, MDB_CREATE, m_spent_keys, "Failed to open db handle for m_spent_keys");
@@ -1057,26 +1057,26 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
bool compatible = true;
- // ND: This "new" version of the lmdb database is incompatible with
- // the previous version. Ensure that the output_keys database is
- // sizeof(output_data_t) in length. Otherwise, inform user and
- // terminate.
- if(m_height > 0)
- {
- MDB_val_copy<uint64_t> k(0);
- MDB_val v;
- auto get_result = mdb_get(txn, m_output_keys, &k, &v);
- if(get_result != MDB_SUCCESS)
- {
- txn.abort();
- m_open = false;
- return;
- }
-
- // LOG_PRINT_L0("Output keys size: " << v.mv_size);
- if(v.mv_size != sizeof(output_data_t))
- compatible = false;
- }
+ // ND: This "new" version of the lmdb database is incompatible with
+ // the previous version. Ensure that the output_keys database is
+ // sizeof(output_data_t) in length. Otherwise, inform user and
+ // terminate.
+ if(m_height > 0)
+ {
+ MDB_val_copy<uint64_t> k(0);
+ MDB_val v;
+ auto get_result = mdb_get(txn, m_output_keys, &k, &v);
+ if(get_result != MDB_SUCCESS)
+ {
+ txn.abort();
+ m_open = false;
+ return;
+ }
+
+ // LOG_PRINT_L0("Output keys size: " << v.mv_size);
+ if(v.mv_size != sizeof(output_data_t))
+ compatible = false;
+ }
MDB_val_copy<const char*> k("version");
MDB_val v;
@@ -1721,11 +1721,11 @@ output_data_t BlockchainLMDB::get_output_key(const uint64_t &global_index) const
output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint64_t& index)
{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- check_open();
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ check_open();
- uint64_t glob_index = get_output_global_index(amount, index);
- return get_output_key(glob_index);
+ uint64_t glob_index = get_output_global_index(amount, index);
+ return get_output_key(glob_index);
}
tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t& index) const
@@ -1760,14 +1760,14 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t&
tx_out_index BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const uint64_t& index)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- std::vector < uint64_t > offsets;
- std::vector<tx_out_index> indices;
- offsets.push_back(index);
- get_output_tx_and_index(amount, offsets, indices);
- if (!indices.size())
+ std::vector < uint64_t > offsets;
+ std::vector<tx_out_index> indices;
+ offsets.push_back(index);
+ get_output_tx_and_index(amount, offsets, indices);
+ if (!indices.size())
throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
- return indices[0];
+ return indices[0];
}
std::vector<uint64_t> BlockchainLMDB::get_tx_output_indices(const crypto::hash& h) const
@@ -2152,7 +2152,7 @@ void BlockchainLMDB::set_batch_transactions(bool batch_transactions)
}
uint64_t BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
- const std::vector<transaction>& txs)
+ const std::vector<transaction>& txs)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -2235,192 +2235,192 @@ void BlockchainLMDB::pop_block(block& blk, std::vector<transaction>& txs)
}
void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint64_t> &global_indices,
- std::vector<tx_out_index> &tx_out_indices) const
+ std::vector<tx_out_index> &tx_out_indices) const
{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- check_open();
- tx_out_indices.clear();
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ check_open();
+ tx_out_indices.clear();
- TXN_PREFIX_RDONLY();
+ TXN_PREFIX_RDONLY();
- for (const uint64_t &index : global_indices)
- {
- MDB_val_copy<uint64_t> k(index);
- MDB_val v;
+ for (const uint64_t &index : global_indices)
+ {
+ MDB_val_copy<uint64_t> k(index);
+ MDB_val v;
- auto get_result = mdb_get(*txn_ptr, m_output_txs, &k, &v);
- if (get_result == MDB_NOTFOUND)
- throw1(OUTPUT_DNE("output with given index not in db"));
- else if (get_result)
- throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
+ auto get_result = mdb_get(*txn_ptr, m_output_txs, &k, &v);
+ if (get_result == MDB_NOTFOUND)
+ throw1(OUTPUT_DNE("output with given index not in db"));
+ else if (get_result)
+ throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
- crypto::hash tx_hash = *(const crypto::hash*) v.mv_data;
+ crypto::hash tx_hash = *(const crypto::hash*) v.mv_data;
- get_result = mdb_get(*txn_ptr, m_output_indices, &k, &v);
- if (get_result == MDB_NOTFOUND)
- throw1(OUTPUT_DNE("output with given index not in db"));
- else if (get_result)
- throw0(DB_ERROR("DB error attempting to fetch output tx index"));
+ get_result = mdb_get(*txn_ptr, m_output_indices, &k, &v);
+ if (get_result == MDB_NOTFOUND)
+ throw1(OUTPUT_DNE("output with given index not in db"));
+ else if (get_result)
+ throw0(DB_ERROR("DB error attempting to fetch output tx index"));
- auto result = tx_out_index(tx_hash, *(const uint64_t *) v.mv_data);
- tx_out_indices.push_back(result);
- }
+ auto result = tx_out_index(tx_hash, *(const uint64_t *) v.mv_data);
+ tx_out_indices.push_back(result);
+ }
- TXN_POSTFIX_SUCCESS();
+ TXN_POSTFIX_SUCCESS();
}
void BlockchainLMDB::get_output_global_indices(const uint64_t& amount, const std::vector<uint64_t> &offsets,
- std::vector<uint64_t> &global_indices)
-{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- TIME_MEASURE_START(txx);
- check_open();
- global_indices.clear();
-
- uint64_t max = 0;
- for (const uint64_t &index : offsets)
- {
- if (index > max)
- max = index;
- }
-
- TXN_PREFIX_RDONLY();
-
- lmdb_cur cur(*txn_ptr, m_output_amounts);
-
- MDB_val_copy<uint64_t> k(amount);
- MDB_val v;
- auto result = mdb_cursor_get(cur, &k, &v, MDB_SET);
- if (result == MDB_NOTFOUND)
- throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
- else if (result)
- throw0(DB_ERROR("DB error attempting to get an output"));
-
- size_t num_elems = 0;
- mdb_cursor_count(cur, &num_elems);
- if (max <= 1 && num_elems <= max)
- throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but output not found"));
-
- uint64_t t_dbmul = 0;
- uint64_t t_dbscan = 0;
- if (max <= 1)
- {
- for (const uint64_t& index : offsets)
- {
- mdb_cursor_get(cur, &k, &v, MDB_FIRST_DUP);
- for (uint64_t i = 0; i < index; ++i)
- {
- mdb_cursor_get(cur, &k, &v, MDB_NEXT_DUP);
- }
-
- mdb_cursor_get(cur, &k, &v, MDB_GET_CURRENT);
- uint64_t glob_index = *(const uint64_t*) v.mv_data;
- LOG_PRINT_L3("Amount: " << amount << " M0->v: " << glob_index);
- global_indices.push_back(glob_index);
- }
- }
- else
- {
- uint32_t curcount = 0;
- uint32_t blockstart = 0;
- for (const uint64_t& index : offsets)
- {
- if (index >= num_elems)
- {
- LOG_PRINT_L1("Index: " << index << " Elems: " << num_elems << " partial results found for get_output_tx_and_index");
- break;
- }
- while (index >= curcount)
- {
- TIME_MEASURE_START(db1);
- if (mdb_cursor_get(cur, &k, &v, curcount == 0 ? MDB_GET_MULTIPLE : MDB_NEXT_MULTIPLE) != 0)
- {
- // allow partial results
- result = false;
- break;
- }
-
- int count = v.mv_size / sizeof(uint64_t);
-
- blockstart = curcount;
- curcount += count;
- TIME_MEASURE_FINISH(db1);
- t_dbmul += db1;
- }
-
- LOG_PRINT_L3("Records returned: " << curcount << " Index: " << index);
- TIME_MEASURE_START(db2);
- uint64_t actual_index = index - blockstart;
- uint64_t glob_index = ((const uint64_t*) v.mv_data)[actual_index];
-
- LOG_PRINT_L3("Amount: " << amount << " M1->v: " << glob_index);
- global_indices.push_back(glob_index);
-
- TIME_MEASURE_FINISH(db2);
- t_dbscan += db2;
-
- }
- }
-
- cur.close();
- TXN_POSTFIX_SUCCESS();
-
- TIME_MEASURE_FINISH(txx);
- LOG_PRINT_L3("txx: " << txx << " db1: " << t_dbmul << " db2: " << t_dbscan);
+ std::vector<uint64_t> &global_indices)
+{
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ TIME_MEASURE_START(txx);
+ check_open();
+ global_indices.clear();
+
+ uint64_t max = 0;
+ for (const uint64_t &index : offsets)
+ {
+ if (index > max)
+ max = index;
+ }
+
+ TXN_PREFIX_RDONLY();
+
+ lmdb_cur cur(*txn_ptr, m_output_amounts);
+
+ MDB_val_copy<uint64_t> k(amount);
+ MDB_val v;
+ auto result = mdb_cursor_get(cur, &k, &v, MDB_SET);
+ if (result == MDB_NOTFOUND)
+ throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
+ else if (result)
+ throw0(DB_ERROR("DB error attempting to get an output"));
+
+ size_t num_elems = 0;
+ mdb_cursor_count(cur, &num_elems);
+ if (max <= 1 && num_elems <= max)
+ throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but output not found"));
+
+ uint64_t t_dbmul = 0;
+ uint64_t t_dbscan = 0;
+ if (max <= 1)
+ {
+ for (const uint64_t& index : offsets)
+ {
+ mdb_cursor_get(cur, &k, &v, MDB_FIRST_DUP);
+ for (uint64_t i = 0; i < index; ++i)
+ {
+ mdb_cursor_get(cur, &k, &v, MDB_NEXT_DUP);
+ }
+
+ mdb_cursor_get(cur, &k, &v, MDB_GET_CURRENT);
+ uint64_t glob_index = *(const uint64_t*) v.mv_data;
+ LOG_PRINT_L3("Amount: " << amount << " M0->v: " << glob_index);
+ global_indices.push_back(glob_index);
+ }
+ }
+ else
+ {
+ uint32_t curcount = 0;
+ uint32_t blockstart = 0;
+ for (const uint64_t& index : offsets)
+ {
+ if (index >= num_elems)
+ {
+ LOG_PRINT_L1("Index: " << index << " Elems: " << num_elems << " partial results found for get_output_tx_and_index");
+ break;
+ }
+ while (index >= curcount)
+ {
+ TIME_MEASURE_START(db1);
+ if (mdb_cursor_get(cur, &k, &v, curcount == 0 ? MDB_GET_MULTIPLE : MDB_NEXT_MULTIPLE) != 0)
+ {
+ // allow partial results
+ result = false;
+ break;
+ }
+
+ int count = v.mv_size / sizeof(uint64_t);
+
+ blockstart = curcount;
+ curcount += count;
+ TIME_MEASURE_FINISH(db1);
+ t_dbmul += db1;
+ }
+
+ LOG_PRINT_L3("Records returned: " << curcount << " Index: " << index);
+ TIME_MEASURE_START(db2);
+ uint64_t actual_index = index - blockstart;
+ uint64_t glob_index = ((const uint64_t*) v.mv_data)[actual_index];
+
+ LOG_PRINT_L3("Amount: " << amount << " M1->v: " << glob_index);
+ global_indices.push_back(glob_index);
+
+ TIME_MEASURE_FINISH(db2);
+ t_dbscan += db2;
+
+ }
+ }
+
+ cur.close();
+ TXN_POSTFIX_SUCCESS();
+
+ TIME_MEASURE_FINISH(txx);
+ LOG_PRINT_L3("txx: " << txx << " db1: " << t_dbmul << " db2: " << t_dbscan);
}
void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs)
{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- TIME_MEASURE_START(db3);
- check_open();
- outputs.clear();
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ TIME_MEASURE_START(db3);
+ check_open();
+ outputs.clear();
- std::vector <uint64_t> global_indices;
- get_output_global_indices(amount, offsets, global_indices);
+ std::vector <uint64_t> global_indices;
+ get_output_global_indices(amount, offsets, global_indices);
- if (global_indices.size() > 0)
- {
- TXN_PREFIX_RDONLY();
+ if (global_indices.size() > 0)
+ {
+ TXN_PREFIX_RDONLY();
- for (const uint64_t &index : global_indices)
- {
- MDB_val_copy<uint64_t> k(index);
- MDB_val v;
+ for (const uint64_t &index : global_indices)
+ {
+ MDB_val_copy<uint64_t> k(index);
+ MDB_val v;
- auto get_result = mdb_get(*txn_ptr, m_output_keys, &k, &v);
- if (get_result == MDB_NOTFOUND)
- throw1(OUTPUT_DNE("Attempting to get output pubkey by global index, but key does not exist"));
- else if (get_result)
- throw0(DB_ERROR("Error attempting to retrieve an output pubkey from the db"));
+ auto get_result = mdb_get(*txn_ptr, m_output_keys, &k, &v);
+ if (get_result == MDB_NOTFOUND)
+ throw1(OUTPUT_DNE("Attempting to get output pubkey by global index, but key does not exist"));
+ else if (get_result)
+ throw0(DB_ERROR("Error attempting to retrieve an output pubkey from the db"));
- output_data_t data = *(const output_data_t *) v.mv_data;
- outputs.push_back(data);
- }
+ output_data_t data = *(const output_data_t *) v.mv_data;
+ outputs.push_back(data);
+ }
- TXN_POSTFIX_SUCCESS();
- }
+ TXN_POSTFIX_SUCCESS();
+ }
- TIME_MEASURE_FINISH(db3);
- LOG_PRINT_L3("db3: " << db3);
+ TIME_MEASURE_FINISH(db3);
+ LOG_PRINT_L3("db3: " << db3);
}
void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices)
{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- check_open();
- indices.clear();
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ check_open();
+ indices.clear();
- std::vector <uint64_t> global_indices;
- get_output_global_indices(amount, offsets, global_indices);
+ std::vector <uint64_t> global_indices;
+ get_output_global_indices(amount, offsets, global_indices);
- TIME_MEASURE_START(db3);
- if(global_indices.size() > 0)
- {
- get_output_tx_and_index_from_global(global_indices, indices);
- }
- TIME_MEASURE_FINISH(db3);
- LOG_PRINT_L3("db3: " << db3);
+ TIME_MEASURE_START(db3);
+ if(global_indices.size() > 0)
+ {
+ get_output_tx_and_index_from_global(global_indices, indices);
+ }
+ TIME_MEASURE_FINISH(db3);
+ LOG_PRINT_L3("db3: " << db3);
}
void BlockchainLMDB::set_hard_fork_starting_height(uint8_t version, uint64_t height)
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 9e45e26cc..d1d3b942d 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -1,20 +1,20 @@
// Copyright (c) 2014, The Monero Project
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -165,7 +165,7 @@ public:
virtual tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const;
virtual void get_output_tx_and_index_from_global(const std::vector<uint64_t> &global_indices,
- std::vector<tx_out_index> &tx_out_indices) const;
+ std::vector<tx_out_index> &tx_out_indices) const;
virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index);
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices);
diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c
index 3fa3d4d07..26adaad62 100644
--- a/src/blocks/blockexports.c
+++ b/src/blocks/blockexports.c
@@ -49,18 +49,18 @@ extern const unsigned char _binary_testnet_blocks_end[];
const unsigned char *get_blocks_dat_start(int testnet)
{
- if (testnet)
- return _binary_testnet_blocks_start;
- else
- return _binary_blocks_start;
+ if (testnet)
+ return _binary_testnet_blocks_start;
+ else
+ return _binary_blocks_start;
}
size_t get_blocks_dat_size(int testnet)
{
- if (testnet)
- return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start);
- else
- return (size_t) (_binary_blocks_end - _binary_blocks_start);
+ if (testnet)
+ return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start);
+ else
+ return (size_t) (_binary_blocks_end - _binary_blocks_start);
}
#endif
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp
index 2ae5d9624..5bb64d4e5 100644
--- a/src/common/dns_utils.cpp
+++ b/src/common/dns_utils.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -86,7 +86,7 @@ get_builtin_cert(void)
static const char*
get_builtin_ds(void)
{
- return
+ return
". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n";
}
@@ -183,30 +183,51 @@ struct DNSResolverData
DNSResolver::DNSResolver() : m_data(new DNSResolverData())
{
+ int use_dns_public = 0;
+ const char* dns_public_addr = "8.8.4.4";
+ if (auto res = getenv("DNS_PUBLIC"))
+ {
+ std::string dns_public(res);
+ // TODO: could allow parsing of IP and protocol: e.g. DNS_PUBLIC=tcp:8.8.8.8
+ if (dns_public == "tcp")
+ {
+ LOG_PRINT_L0("Using public DNS server: " << dns_public_addr << " (TCP)");
+ use_dns_public = 1;
+ }
+ }
+
// init libunbound context
m_data->m_ub_context = ub_ctx_create();
- // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent
- ub_ctx_resolvconf(m_data->m_ub_context, NULL);
- ub_ctx_hosts(m_data->m_ub_context, NULL);
-
- #ifdef DEVELOPER_LIBUNBOUND_OLD
- #pragma message "Using the work around for old libunbound"
- { // work around for bug https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=515 needed for it to compile on e.g. Debian 7
- char * ds_copy = NULL; // this will be the writable copy of string that bugged version of libunbound requires
- try {
- char * ds_copy = strdup( ::get_builtin_ds() );
- ub_ctx_add_ta(m_data->m_ub_context, ds_copy);
- } catch(...) { // probably not needed but to work correctly in every case...
- if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup
- throw ;
- }
- if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup
- }
- #else
- // normal version for fixed libunbound
- ub_ctx_add_ta(m_data->m_ub_context, ::get_builtin_ds() );
- #endif
+ if (use_dns_public)
+ {
+ ub_ctx_set_fwd(m_data->m_ub_context, dns_public_addr);
+ ub_ctx_set_option(m_data->m_ub_context, "do-udp:", "no");
+ ub_ctx_set_option(m_data->m_ub_context, "do-tcp:", "yes");
+ }
+ else {
+ // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent
+ ub_ctx_resolvconf(m_data->m_ub_context, NULL);
+ ub_ctx_hosts(m_data->m_ub_context, NULL);
+ }
+
+ #ifdef DEVELOPER_LIBUNBOUND_OLD
+ #pragma message "Using the work around for old libunbound"
+ { // work around for bug https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=515 needed for it to compile on e.g. Debian 7
+ char * ds_copy = NULL; // this will be the writable copy of string that bugged version of libunbound requires
+ try {
+ char * ds_copy = strdup( ::get_builtin_ds() );
+ ub_ctx_add_ta(m_data->m_ub_context, ds_copy);
+ } catch(...) { // probably not needed but to work correctly in every case...
+ if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup
+ throw ;
+ }
+ if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup
+ }
+ #else
+ // normal version for fixed libunbound
+ ub_ctx_add_ta(m_data->m_ub_context, ::get_builtin_ds() );
+ #endif
}
diff --git a/src/crypto/aesb.c b/src/crypto/aesb.c
index 128c523ea..5d57b8af4 100644
--- a/src/crypto/aesb.c
+++ b/src/crypto/aesb.c
@@ -25,11 +25,11 @@ extern "C"
{
#endif
-#define TABLE_ALIGN 32
-#define WPOLY 0x011b
-#define N_COLS 4
-#define AES_BLOCK_SIZE 16
-#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
+#define TABLE_ALIGN 32
+#define WPOLY 0x011b
+#define N_COLS 4
+#define AES_BLOCK_SIZE 16
+#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
#if defined(_MSC_VER)
#define ALIGN __declspec(align(TABLE_ALIGN))
@@ -61,45 +61,45 @@ extern "C"
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
#define sb_data(w) {\
- w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
- w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
- w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
- w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
- w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
- w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
- w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
- w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
- w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
- w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
- w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
- w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
- w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
- w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
- w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
- w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
- w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
- w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
- w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
- w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
- w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
- w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
- w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
- w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
- w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
- w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
- w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
- w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
- w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
- w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
- w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
- w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
+ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+ w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+ w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+ w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+ w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+ w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+ w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+ w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+ w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+ w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+ w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+ w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+ w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+ w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+ w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+ w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+ w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+ w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+ w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+ w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+ w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+ w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+ w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+ w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+ w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+ w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+ w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+ w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
#define rc_data(w) {\
- w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\
- w(0x1b), w(0x36) }
+ w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\
+ w(0x1b), w(0x36) }
#define bytes2word(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \
- ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
+ ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
#define h0(x) (x)
#define w0(p) bytes2word(p, 0, 0, 0)
@@ -133,10 +133,10 @@ extern "C"
#define d_4(t,n,b,e,f,g,h) ALIGN const t n[4][256] = { b(e), b(f), b(g), b(h) }
#define four_tables(x,tab,vf,rf,c) \
- (tab[0][bval(vf(x,0,c),rf(0,c))] \
- ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
- ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
- ^ tab[3][bval(vf(x,3,c),rf(3,c))])
+ (tab[0][bval(vf(x,0,c),rf(0,c))] \
+ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
+ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
+ ^ tab[3][bval(vf(x,3,c),rf(3,c))])
d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3);
@@ -149,34 +149,34 @@ d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3);
#endif
STATIC INLINE void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
-{
- uint32_t b0[4], b1[4];
- const uint32_t *kp = (uint32_t *) expandedKey;
- state_in(b0, in);
+{
+ uint32_t b0[4], b1[4];
+ const uint32_t *kp = (uint32_t *) expandedKey;
+ state_in(b0, in);
- round(fwd_rnd, b1, b0, kp);
+ round(fwd_rnd, b1, b0, kp);
- state_out(out, b1);
+ state_out(out, b1);
}
STATIC INLINE void aesb_pseudo_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
-{
- uint32_t b0[4], b1[4];
- const uint32_t *kp = (uint32_t *) expandedKey;
- state_in(b0, in);
-
- round(fwd_rnd, b1, b0, kp);
- round(fwd_rnd, b0, b1, kp + 1 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 2 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 3 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 4 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 5 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 6 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 7 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 8 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 9 * N_COLS);
-
- state_out(out, b0);
+{
+ uint32_t b0[4], b1[4];
+ const uint32_t *kp = (uint32_t *) expandedKey;
+ state_in(b0, in);
+
+ round(fwd_rnd, b1, b0, kp);
+ round(fwd_rnd, b0, b1, kp + 1 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 2 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 3 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 4 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 5 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 6 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 7 * N_COLS);
+ round(fwd_rnd, b1, b0, kp + 8 * N_COLS);
+ round(fwd_rnd, b0, b1, kp + 9 * N_COLS);
+
+ state_out(out, b0);
}
diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c
index 2a746de3d..51ad2f40b 100644
--- a/src/crypto/slow-hash.c
+++ b/src/crypto/slow-hash.c
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <assert.h>
@@ -104,33 +104,33 @@
#endif
#define pre_aes() \
- j = state_index(a); \
- _c = _mm_load_si128(R128(&hp_state[j])); \
- _a = _mm_load_si128(R128(a)); \
+ j = state_index(a); \
+ _c = _mm_load_si128(R128(&hp_state[j])); \
+ _a = _mm_load_si128(R128(a)); \
/*
* An SSE-optimized implementation of the second half of CryptoNight step 3.
- * After using AES to mix a scratchpad value into _c (done by the caller),
- * this macro xors it with _b and stores the result back to the same index (j) that it
+ * After using AES to mix a scratchpad value into _c (done by the caller),
+ * this macro xors it with _b and stores the result back to the same index (j) that it
* loaded the scratchpad value from. It then performs a second random memory
* read/write from the scratchpad, but this time mixes the values using a 64
* bit multiply.
* This code is based upon an optimized implementation by dga.
*/
#define post_aes() \
- _mm_store_si128(R128(c), _c); \
- _b = _mm_xor_si128(_b, _c); \
- _mm_store_si128(R128(&hp_state[j]), _b); \
- j = state_index(c); \
- p = U64(&hp_state[j]); \
- b[0] = p[0]; b[1] = p[1]; \
- __mul(); \
- a[0] += hi; a[1] += lo; \
- p = U64(&hp_state[j]); \
- p[0] = a[0]; p[1] = a[1]; \
- a[0] ^= b[0]; a[1] ^= b[1]; \
- _b = _c; \
-
+ _mm_store_si128(R128(c), _c); \
+ _b = _mm_xor_si128(_b, _c); \
+ _mm_store_si128(R128(&hp_state[j]), _b); \
+ j = state_index(c); \
+ p = U64(&hp_state[j]); \
+ b[0] = p[0]; b[1] = p[1]; \
+ __mul(); \
+ a[0] += hi; a[1] += lo; \
+ p = U64(&hp_state[j]); \
+ p[0] = a[0]; p[1] = a[1]; \
+ a[0] ^= b[0]; a[1] ^= b[1]; \
+ _b = _c; \
+
#if defined(_MSC_VER)
#define THREADV __declspec(thread)
#else
@@ -226,14 +226,14 @@ STATIC INLINE void aes_256_assist2(__m128i* t1, __m128i * t3)
*t3 = _mm_xor_si128(*t3, t2);
}
-/**
+/**
* @brief expands 'key' into a form it can be used for AES encryption.
- *
+ *
* This is an SSE-optimized implementation of AES key schedule generation. It
* expands the key into multiple round keys, each of which is used in one round
* of the AES encryption used to fill (and later, extract randomness from)
* the large 2MB buffer. Note that CryptoNight does not use a completely
- * standard AES encryption for its buffer expansion, so do not copy this
+ * standard AES encryption for its buffer expansion, so do not copy this
* function outside of Monero without caution! This version uses the hardware
* AESKEYGENASSIST instruction to speed key generation, and thus requires
* CPU AES support.
@@ -402,7 +402,7 @@ BOOL SetLockPagesPrivilege(HANDLE hProcess, BOOL bEnable)
/**
* @brief allocate the 2MB scratch buffer using OS support for huge pages, if available
*
- * This function tries to allocate the 2MB scratch buffer using a single
+ * This function tries to allocate the 2MB scratch buffer using a single
* 2MB "huge page" (instead of the usual 4KB page sizes) to reduce TLB misses
* during the random accesses to the scratch buffer. This is one of the
* important speed optimizations needed to make CryptoNight faster.
@@ -423,7 +423,7 @@ void slow_hash_allocate_state(void)
#else
#if defined(__APPLE__) || defined(__FreeBSD__)
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON, 0, 0);
+ MAP_PRIVATE | MAP_ANON, 0, 0);
#else
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, 0, 0);
@@ -562,7 +562,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
*/
_b = _mm_load_si128(R128(b));
- // Two independent versions, one with AES, one without, to ensure that
+ // Two independent versions, one with AES, one without, to ensure that
// the useAes test is only performed once, not every iteration.
if(useAes)
{
@@ -665,59 +665,59 @@ static void (*const extra_hashes[4])(const void *, size_t, char *) = {
STATIC INLINE void ___mul128(uint32_t *a, uint32_t *b, uint32_t *h, uint32_t *l)
{
- // ND: 64x64 multiplication for ARM7
- __asm__ __volatile__
- (
- // lo hi
- "umull %[r0], %[r1], %[b], %[d]\n\t" // bd [r0 = bd.lo]
- "umull %[r2], %[r3], %[b], %[c]\n\t" // bc
- "umull %[b], %[c], %[a], %[c]\n\t" // ac
- "adds %[r1], %[r1], %[r2]\n\t" // r1 = bd.hi + bc.lo
- "adcs %[r2], %[r3], %[b]\n\t" // r2 = ac.lo + bc.hi + carry
- "adc %[r3], %[c], #0\n\t" // r3 = ac.hi + carry
- "umull %[b], %[a], %[a], %[d]\n\t" // ad
- "adds %[r1], %[r1], %[b]\n\t" // r1 = bd.hi + bc.lo + ad.lo
- "adcs %[r2], %[r2], %[a]\n\t" // r2 = ac.lo + bc.hi + ad.hi + carry
- "adc %[r3], %[r3], #0\n\t" // r3 = ac.hi + carry
- : [r0]"=&r"(l[0]), [r1]"=&r"(l[1]), [r2]"=&r"(h[0]), [r3]"=&r"(h[1])
- : [a]"r"(a[1]), [b]"r"(a[0]), [c]"r"(b[1]), [d]"r"(b[0])
- : "cc"
- );
+ // ND: 64x64 multiplication for ARM7
+ __asm__ __volatile__
+ (
+ // lo hi
+ "umull %[r0], %[r1], %[b], %[d]\n\t" // bd [r0 = bd.lo]
+ "umull %[r2], %[r3], %[b], %[c]\n\t" // bc
+ "umull %[b], %[c], %[a], %[c]\n\t" // ac
+ "adds %[r1], %[r1], %[r2]\n\t" // r1 = bd.hi + bc.lo
+ "adcs %[r2], %[r3], %[b]\n\t" // r2 = ac.lo + bc.hi + carry
+ "adc %[r3], %[c], #0\n\t" // r3 = ac.hi + carry
+ "umull %[b], %[a], %[a], %[d]\n\t" // ad
+ "adds %[r1], %[r1], %[b]\n\t" // r1 = bd.hi + bc.lo + ad.lo
+ "adcs %[r2], %[r2], %[a]\n\t" // r2 = ac.lo + bc.hi + ad.hi + carry
+ "adc %[r3], %[r3], #0\n\t" // r3 = ac.hi + carry
+ : [r0]"=&r"(l[0]), [r1]"=&r"(l[1]), [r2]"=&r"(h[0]), [r3]"=&r"(h[1])
+ : [a]"r"(a[1]), [b]"r"(a[0]), [c]"r"(b[1]), [d]"r"(b[0])
+ : "cc"
+ );
}
STATIC INLINE void mul(const uint8_t* a, const uint8_t* b, uint8_t* res)
{
- ___mul128((uint32_t *) a, (uint32_t *) b, (uint32_t *) (res + 0), (uint32_t *) (res + 8));
+ ___mul128((uint32_t *) a, (uint32_t *) b, (uint32_t *) (res + 0), (uint32_t *) (res + 8));
}
STATIC INLINE void sum_half_blocks(uint8_t* a, const uint8_t* b)
{
- uint64_t a0, a1, b0, b1;
- a0 = U64(a)[0];
- a1 = U64(a)[1];
- b0 = U64(b)[0];
- b1 = U64(b)[1];
- a0 += b0;
- a1 += b1;
- U64(a)[0] = a0;
- U64(a)[1] = a1;
+ uint64_t a0, a1, b0, b1;
+ a0 = U64(a)[0];
+ a1 = U64(a)[1];
+ b0 = U64(b)[0];
+ b1 = U64(b)[1];
+ a0 += b0;
+ a1 += b1;
+ U64(a)[0] = a0;
+ U64(a)[1] = a1;
}
STATIC INLINE void swap_blocks(uint8_t *a, uint8_t *b)
{
- uint64_t t[2];
- U64(t)[0] = U64(a)[0];
- U64(t)[1] = U64(a)[1];
- U64(a)[0] = U64(b)[0];
- U64(a)[1] = U64(b)[1];
- U64(b)[0] = U64(t)[0];
- U64(b)[1] = U64(t)[1];
+ uint64_t t[2];
+ U64(t)[0] = U64(a)[0];
+ U64(t)[1] = U64(a)[1];
+ U64(a)[0] = U64(b)[0];
+ U64(a)[1] = U64(b)[1];
+ U64(b)[0] = U64(t)[0];
+ U64(b)[1] = U64(t)[1];
}
STATIC INLINE void xor_blocks(uint8_t* a, const uint8_t* b)
{
- U64(a)[0] ^= U64(b)[0];
- U64(a)[1] ^= U64(b)[1];
+ U64(a)[0] ^= U64(b)[0];
+ U64(a)[1] ^= U64(b)[1];
}
#pragma pack(push, 1)
@@ -774,25 +774,25 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
for(i = 0; i < ITER / 2; i++)
{
- #define MASK ((uint32_t)(((MEMORY / AES_BLOCK_SIZE) - 1) << 4))
- #define state_index(x) ((*(uint32_t *) x) & MASK)
+ #define MASK ((uint32_t)(((MEMORY / AES_BLOCK_SIZE) - 1) << 4))
+ #define state_index(x) ((*(uint32_t *) x) & MASK)
- // Iteration 1
- p = &long_state[state_index(a)];
- aesb_single_round(p, p, a);
+ // Iteration 1
+ p = &long_state[state_index(a)];
+ aesb_single_round(p, p, a);
- xor_blocks(b, p);
- swap_blocks(b, p);
- swap_blocks(a, b);
+ xor_blocks(b, p);
+ swap_blocks(b, p);
+ swap_blocks(a, b);
- // Iteration 2
- p = &long_state[state_index(a)];
+ // Iteration 2
+ p = &long_state[state_index(a)];
- mul(a, p, d);
- sum_half_blocks(b, d);
- swap_blocks(b, p);
- xor_blocks(b, p);
- swap_blocks(a, b);
+ mul(a, p, d);
+ sum_half_blocks(b, d);
+ swap_blocks(b, p);
+ xor_blocks(b, p);
+ swap_blocks(a, b);
}
memcpy(text, state.init, INIT_SIZE_BYTE);
@@ -874,13 +874,13 @@ static void copy_block(uint8_t* dst, const uint8_t* src) {
}
static void swap_blocks(uint8_t *a, uint8_t *b){
- uint64_t t[2];
- U64(t)[0] = U64(a)[0];
- U64(t)[1] = U64(a)[1];
- U64(a)[0] = U64(b)[0];
- U64(a)[1] = U64(b)[1];
- U64(b)[0] = U64(t)[0];
- U64(b)[1] = U64(t)[1];
+ uint64_t t[2];
+ U64(t)[0] = U64(a)[0];
+ U64(t)[1] = U64(a)[1];
+ U64(a)[0] = U64(b)[0];
+ U64(a)[1] = U64(b)[1];
+ U64(b)[0] = U64(t)[0];
+ U64(b)[1] = U64(t)[1];
}
static void xor_blocks(uint8_t* a, const uint8_t* b) {
@@ -916,11 +916,11 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
memcpy(text, state.init, INIT_SIZE_BYTE);
memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
aes_ctx = (oaes_ctx *) oaes_alloc();
-
+
oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE);
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
- for (j = 0; j < INIT_SIZE_BLK; j++) {
- aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
+ for (j = 0; j < INIT_SIZE_BLK; j++) {
+ aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
}
memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
}
@@ -938,7 +938,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
/* Iteration 1 */
j = e2i(a, MEMORY / AES_BLOCK_SIZE);
copy_block(c, &long_state[j * AES_BLOCK_SIZE]);
- aesb_single_round(c, c, a);
+ aesb_single_round(c, c, a);
xor_blocks(b, c);
swap_blocks(b, c);
copy_block(&long_state[j * AES_BLOCK_SIZE], c);
@@ -961,7 +961,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash) {
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
for (j = 0; j < INIT_SIZE_BLK; j++) {
xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
- aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
+ aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
}
}
memcpy(state.init, text, INIT_SIZE_BYTE);
diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt
index 7b0a5017d..4aaad88a2 100644
--- a/src/cryptonote_core/CMakeLists.txt
+++ b/src/cryptonote_core/CMakeLists.txt
@@ -65,9 +65,9 @@ set(cryptonote_core_private_headers
hardfork.h)
if(PER_BLOCK_CHECKPOINT)
- set(Blocks "blocks")
+ set(Blocks "blocks")
else()
- set(Blocks "")
+ set(Blocks "")
endif()
bitmonero_private_headers(cryptonote_core
@@ -86,7 +86,7 @@ target_link_libraries(cryptonote_core
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_SERIALIZATION_LIBRARY}
LINK_PRIVATE
- ${Blocks}
+ ${Blocks}
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 31945d166..bf7294375 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <algorithm>
@@ -99,24 +99,24 @@ static const uint64_t testnet_hard_fork_version_1_till = 624633;
//------------------------------------------------------------------
Blockchain::Blockchain(tx_memory_pool& tx_pool) :
-m_db(), m_tx_pool(tx_pool), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false),
-m_is_blockchain_storing(false), m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_fast_sync(true)
+ m_db(), m_tx_pool(tx_pool), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false),
+ m_is_blockchain_storing(false), m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_fast_sync(true)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
+ LOG_PRINT_L3("Blockchain::" << __func__);
}
//------------------------------------------------------------------
bool Blockchain::have_tx(const crypto::hash &id) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- return m_db->tx_exists(id);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ return m_db->tx_exists(id);
}
//------------------------------------------------------------------
bool Blockchain::have_tx_keyimg_as_spent(const crypto::key_image &key_im) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- return m_db->has_key_image(key_im);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ return m_db->has_key_image(key_im);
}
//------------------------------------------------------------------
// This function makes sure that each "input" in an input (mixins) exists
@@ -125,305 +125,305 @@ bool Blockchain::have_tx_keyimg_as_spent(const crypto::key_image &key_im) const
template <class visitor_t>
bool Blockchain::scan_outputkeys_for_indexes(const txin_to_key& tx_in_to_key, visitor_t &vis, const crypto::hash &tx_prefix_hash, uint64_t* pmax_related_block_height) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
-
- // ND: Disable locking and make method private.
- //CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
- // verify that the input has key offsets (that it exists properly, really)
- if(!tx_in_to_key.key_offsets.size())
- return false;
+ // ND: Disable locking and make method private.
+ //CRITICAL_REGION_LOCAL(m_blockchain_lock);
- // cryptonote_format_utils uses relative offsets for indexing to the global
- // outputs list. that is to say that absolute offset #2 is absolute offset
- // #1 plus relative offset #2.
- // TODO: Investigate if this is necessary / why this is done.
- std::vector<uint64_t> absolute_offsets = relative_output_offsets_to_absolute(tx_in_to_key.key_offsets);
- std::vector<output_data_t> outputs;
+ // verify that the input has key offsets (that it exists properly, really)
+ if(!tx_in_to_key.key_offsets.size())
+ return false;
- bool found = false;
- auto it = m_scan_table.find(tx_prefix_hash);
- if (it != m_scan_table.end())
+ // cryptonote_format_utils uses relative offsets for indexing to the global
+ // outputs list. that is to say that absolute offset #2 is absolute offset
+ // #1 plus relative offset #2.
+ // TODO: Investigate if this is necessary / why this is done.
+ std::vector<uint64_t> absolute_offsets = relative_output_offsets_to_absolute(tx_in_to_key.key_offsets);
+ std::vector<output_data_t> outputs;
+
+ bool found = false;
+ auto it = m_scan_table.find(tx_prefix_hash);
+ if (it != m_scan_table.end())
+ {
+ auto its = it->second.find(tx_in_to_key.k_image);
+ if (its != it->second.end())
+ {
+ outputs = its->second;
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ m_db->get_output_key(tx_in_to_key.amount, absolute_offsets, outputs);
+ }
+ else
+ {
+ // check for partial results and add the rest if needed;
+ if (outputs.size() < absolute_offsets.size() && outputs.size() > 0)
+ {
+ LOG_PRINT_L1("Additional outputs needed: " << absolute_offsets.size() - outputs.size());
+ std::vector < uint64_t > add_offsets;
+ std::vector<output_data_t> add_outputs;
+ for (size_t i = outputs.size(); i < absolute_offsets.size(); i++)
+ add_offsets.push_back(absolute_offsets[i]);
+ m_db->get_output_key(tx_in_to_key.amount, add_offsets, add_outputs);
+ outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end());
+ }
+ }
+
+ size_t count = 0;
+ for (const uint64_t& i : absolute_offsets)
+ {
+ try
{
- auto its = it->second.find(tx_in_to_key.k_image);
- if (its != it->second.end())
- {
- outputs = its->second;
- found = true;
- }
- }
+ output_data_t output_index;
+ try
+ {
+ // get tx hash and output index for output
+ if (count < outputs.size())
+ output_index = outputs.at(count);
+ else
+ output_index = m_db->get_output_key(tx_in_to_key.amount, i);
- if (!found)
- {
- m_db->get_output_key(tx_in_to_key.amount, absolute_offsets, outputs);
- }
- else
- {
- // check for partial results and add the rest if needed;
- if (outputs.size() < absolute_offsets.size() && outputs.size() > 0)
+ // call to the passed boost visitor to grab the public key for the output
+ if (!vis.handle_output(output_index.unlock_time, output_index.pubkey))
{
- LOG_PRINT_L1("Additional outputs needed: " << absolute_offsets.size() - outputs.size());
- std::vector < uint64_t > add_offsets;
- std::vector<output_data_t> add_outputs;
- for (size_t i = outputs.size(); i < absolute_offsets.size(); i++)
- add_offsets.push_back(absolute_offsets[i]);
- m_db->get_output_key(tx_in_to_key.amount, add_offsets, add_outputs);
- outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end());
+ LOG_PRINT_L0("Failed to handle_output for output no = " << count << ", with absolute offset " << i);
+ return false;
}
- }
-
- size_t count = 0;
- for (const uint64_t& i : absolute_offsets)
- {
- try
- {
- output_data_t output_index;
- try
- {
- // get tx hash and output index for output
- if (count < outputs.size())
- output_index = outputs.at(count);
- else
- output_index = m_db->get_output_key(tx_in_to_key.amount, i);
-
- // call to the passed boost visitor to grab the public key for the output
- if (!vis.handle_output(output_index.unlock_time, output_index.pubkey))
- {
- LOG_PRINT_L0("Failed to handle_output for output no = " << count << ", with absolute offset " << i);
- return false;
- }
- }
- catch (...)
- {
- LOG_PRINT_L0("Output does not exist! amount = " << tx_in_to_key.amount << ", absolute_offset = " << i);
- return false;
- }
-
- // if on last output and pmax_related_block_height not null pointer
- if(++count == absolute_offsets.size() && pmax_related_block_height)
- {
- // set *pmax_related_block_height to tx block height for this output
- auto h = output_index.height;
- if(*pmax_related_block_height < h)
- {
- *pmax_related_block_height = h;
- }
- }
+ }
+ catch (...)
+ {
+ LOG_PRINT_L0("Output does not exist! amount = " << tx_in_to_key.amount << ", absolute_offset = " << i);
+ return false;
+ }
- }
- catch (const OUTPUT_DNE& e)
- {
- LOG_PRINT_L0("Output does not exist: " << e.what());
- return false;
- }
- catch (const TX_DNE& e)
+ // if on last output and pmax_related_block_height not null pointer
+ if(++count == absolute_offsets.size() && pmax_related_block_height)
+ {
+ // set *pmax_related_block_height to tx block height for this output
+ auto h = output_index.height;
+ if(*pmax_related_block_height < h)
{
- LOG_PRINT_L0("Transaction does not exist: " << e.what());
- return false;
+ *pmax_related_block_height = h;
}
+ }
}
+ catch (const OUTPUT_DNE& e)
+ {
+ LOG_PRINT_L0("Output does not exist: " << e.what());
+ return false;
+ }
+ catch (const TX_DNE& e)
+ {
+ LOG_PRINT_L0("Transaction does not exist: " << e.what());
+ return false;
+ }
- return true;
+ }
+
+ return true;
}
//------------------------------------------------------------------
uint64_t Blockchain::get_current_blockchain_height() const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- return m_db->height();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ return m_db->height();
}
//------------------------------------------------------------------
//FIXME: possibly move this into the constructor, to avoid accidentally
// dereferencing a null BlockchainDB pointer
bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
-
- if (db == nullptr)
- {
- LOG_ERROR("Attempted to init Blockchain with null DB");
- return false;
- }
- if (!db->is_open())
- {
- LOG_ERROR("Attempted to init Blockchain with unopened DB");
- return false;
- }
-
- m_db = db;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- if (testnet) {
- m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
- for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n)
- m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
- }
- else
- {
- m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
- for (size_t n = 0; n < sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); ++n)
- m_hardfork->add_fork(mainnet_hard_forks[n].version, mainnet_hard_forks[n].height, mainnet_hard_forks[n].threshold, mainnet_hard_forks[n].time);
- }
- m_hardfork->init();
-
- // if the blockchain is new, add the genesis block
- // this feels kinda kludgy to do it this way, but can be looked at later.
- // TODO: add function to create and store genesis block,
- // taking testnet into account
- if(!m_db->height())
+ if (db == nullptr)
+ {
+ LOG_ERROR("Attempted to init Blockchain with null DB");
+ return false;
+ }
+ if (!db->is_open())
+ {
+ LOG_ERROR("Attempted to init Blockchain with unopened DB");
+ return false;
+ }
+
+ m_db = db;
+
+ if (testnet) {
+ m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
+ for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n)
+ m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
+ }
+ else
+ {
+ m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
+ for (size_t n = 0; n < sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); ++n)
+ m_hardfork->add_fork(mainnet_hard_forks[n].version, mainnet_hard_forks[n].height, mainnet_hard_forks[n].threshold, mainnet_hard_forks[n].time);
+ }
+ m_hardfork->init();
+
+ // if the blockchain is new, add the genesis block
+ // this feels kinda kludgy to do it this way, but can be looked at later.
+ // TODO: add function to create and store genesis block,
+ // taking testnet into account
+ if(!m_db->height())
+ {
+ LOG_PRINT_L0("Blockchain not loaded, generating genesis block.");
+ block bl = boost::value_initialized<block>();
+ block_verification_context bvc = boost::value_initialized<block_verification_context>();
+ if (testnet)
{
- LOG_PRINT_L0("Blockchain not loaded, generating genesis block.");
- block bl = boost::value_initialized<block>();
- block_verification_context bvc = boost::value_initialized<block_verification_context>();
- if (testnet)
- {
- generate_genesis_block(bl, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
- }
- else
- {
- generate_genesis_block(bl, config::GENESIS_TX, config::GENESIS_NONCE);
- }
- add_new_block(bl, bvc);
- CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "Failed to add genesis block to blockchain");
+ generate_genesis_block(bl, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
}
- // TODO: if blockchain load successful, verify blockchain against both
- // hard-coded and runtime-loaded (and enforced) checkpoints.
else
{
+ generate_genesis_block(bl, config::GENESIS_TX, config::GENESIS_NONCE);
}
+ add_new_block(bl, bvc);
+ CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "Failed to add genesis block to blockchain");
+ }
+ // TODO: if blockchain load successful, verify blockchain against both
+ // hard-coded and runtime-loaded (and enforced) checkpoints.
+ else
+ {
+ }
- if (!fakechain)
- {
- // ensure we fixup anything we found and fix in the future
- m_db->fixup();
- }
+ if (!fakechain)
+ {
+ // ensure we fixup anything we found and fix in the future
+ m_db->fixup();
+ }
- // 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;
+ // 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;
- // genesis block has no timestamp, could probably change it to have timestamp of 1341378000...
- if(!top_block_timestamp)
- timestamp_diff = time(NULL) - 1341378000;
+ // genesis block has no timestamp, could probably change it to have timestamp of 1341378000...
+ if(!top_block_timestamp)
+ timestamp_diff = time(NULL) - 1341378000;
- // create general purpose async service queue
+ // create general purpose async service queue
- m_async_work_idle = std::unique_ptr < boost::asio::io_service::work > (new boost::asio::io_service::work(m_async_service));
- // we only need 1
- m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
+ m_async_work_idle = std::unique_ptr < boost::asio::io_service::work > (new boost::asio::io_service::work(m_async_service));
+ // we only need 1
+ m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
#if defined(PER_BLOCK_CHECKPOINT)
- if (!fakechain && m_fast_sync && get_blocks_dat_start(testnet) != nullptr)
- {
- if (get_blocks_dat_size(testnet) > 4)
+ if (!fakechain && m_fast_sync && get_blocks_dat_start(testnet) != nullptr)
+ {
+ if (get_blocks_dat_size(testnet) > 4)
+ {
+ const unsigned char *p = get_blocks_dat_start(testnet);
+ const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
+ const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
+ if(nblocks > 0 && nblocks > m_db->height() && get_blocks_dat_size(testnet) >= size_needed)
+ {
+ LOG_PRINT_L0("Loading precomputed blocks: " << nblocks);
+ p += sizeof(uint32_t);
+ for (uint32_t i = 0; i < nblocks; i++)
+ {
+ crypto::hash hash;
+ memcpy(hash.data, p, sizeof(hash.data));
+ p += sizeof(hash.data);
+ m_blocks_hash_check.push_back(hash);
+ }
+
+ // FIXME: clear tx_pool because the process might have been
+ // terminated and caused it to store txs kept by blocks.
+ // The core will not call check_tx_inputs(..) for these
+ // transactions in this case. Consequently, the sanity check
+ // for tx hashes will fail in handle_block_to_main_chain(..)
+ std::list<transaction> txs;
+ m_tx_pool.get_transactions(txs);
+
+ size_t blob_size;
+ uint64_t fee;
+ bool relayed;
+ transaction pool_tx;
+ for(const transaction &tx : txs)
{
- const unsigned char *p = get_blocks_dat_start(testnet);
- const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
- const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
- if(nblocks > 0 && nblocks > m_db->height() && get_blocks_dat_size(testnet) >= size_needed)
- {
- LOG_PRINT_L0("Loading precomputed blocks: " << nblocks);
- p += sizeof(uint32_t);
- for (uint32_t i = 0; i < nblocks; i++)
- {
- crypto::hash hash;
- memcpy(hash.data, p, sizeof(hash.data));
- p += sizeof(hash.data);
- m_blocks_hash_check.push_back(hash);
- }
-
- // FIXME: clear tx_pool because the process might have been
- // terminated and caused it to store txs kept by blocks.
- // The core will not call check_tx_inputs(..) for these
- // transactions in this case. Consequently, the sanity check
- // for tx hashes will fail in handle_block_to_main_chain(..)
- std::list<transaction> txs;
- m_tx_pool.get_transactions(txs);
-
- size_t blob_size;
- uint64_t fee;
- bool relayed;
- transaction pool_tx;
- for(const transaction &tx : txs)
- {
- crypto::hash tx_hash = get_transaction_hash(tx);
- m_tx_pool.take_tx(tx_hash, pool_tx, blob_size, fee, relayed);
- }
- }
+ crypto::hash tx_hash = get_transaction_hash(tx);
+ m_tx_pool.take_tx(tx_hash, pool_tx, blob_size, fee, relayed);
}
+ }
}
+ }
#endif
- LOG_PRINT_GREEN("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(), LOG_LEVEL_0);
+ LOG_PRINT_GREEN("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(), LOG_LEVEL_0);
- return true;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::store_blockchain()
{
- LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
- // lock because the rpc_thread command handler also calls this
- CRITICAL_REGION_LOCAL(m_db->m_synchronization_lock);
-
- TIME_MEASURE_START(save);
- // TODO: make sure sync(if this throws that it is not simply ignored higher
- // up the call stack
- try
- {
- m_db->sync();
- }
- catch (const std::exception& e)
- {
- LOG_PRINT_L0(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!");
- throw;
- }
- catch (...)
- {
- LOG_PRINT_L0("There was an issue storing the blockchain, shutting down now to prevent issues!");
- throw;
- }
-
- TIME_MEASURE_FINISH(save);
- if(m_show_time_stats)
- LOG_PRINT_L0("Blockchain stored OK, took: " << save << " ms");
- return true;
+ LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
+ // lock because the rpc_thread command handler also calls this
+ CRITICAL_REGION_LOCAL(m_db->m_synchronization_lock);
+
+ TIME_MEASURE_START(save);
+ // TODO: make sure sync(if this throws that it is not simply ignored higher
+ // up the call stack
+ try
+ {
+ m_db->sync();
+ }
+ catch (const std::exception& e)
+ {
+ LOG_PRINT_L0(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!");
+ throw;
+ }
+ catch (...)
+ {
+ LOG_PRINT_L0("There was an issue storing the blockchain, shutting down now to prevent issues!");
+ throw;
+ }
+
+ TIME_MEASURE_FINISH(save);
+ if(m_show_time_stats)
+ LOG_PRINT_L0("Blockchain stored OK, took: " << save << " ms");
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::deinit()
{
- LOG_PRINT_L3("Blockchain::" << __func__);
+ LOG_PRINT_L3("Blockchain::" << __func__);
- LOG_PRINT_L0("Closing IO Service.")
+ LOG_PRINT_L0("Closing IO Service.")
// stop async service
m_async_work_idle.reset();
- m_async_pool.join_all();
- m_async_service.stop();
-
- // as this should be called if handling a SIGSEGV, need to check
- // if m_db is a NULL pointer (and thus may have caused the illegal
- // memory operation), otherwise we may cause a loop.
- if (m_db == NULL)
- {
- throw new DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!");
- }
-
- try
- {
- m_db->close();
- }
- catch (const std::exception& e)
- {
- LOG_PRINT_L0(std::string("Error closing blockchain db: ") + e.what());
- }
- catch (...)
- {
- LOG_PRINT_L0("There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
- }
-
- delete m_hardfork;
- delete m_db;
- return true;
+ m_async_pool.join_all();
+ m_async_service.stop();
+
+ // as this should be called if handling a SIGSEGV, need to check
+ // if m_db is a NULL pointer (and thus may have caused the illegal
+ // memory operation), otherwise we may cause a loop.
+ if (m_db == NULL)
+ {
+ throw new DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!");
+ }
+
+ try
+ {
+ m_db->close();
+ }
+ catch (const std::exception& e)
+ {
+ LOG_PRINT_L0(std::string("Error closing blockchain db: ") + e.what());
+ }
+ catch (...)
+ {
+ LOG_PRINT_L0("There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
+ }
+
+ delete m_hardfork;
+ delete m_db;
+ return true;
}
//------------------------------------------------------------------
// This function tells BlockchainDB to remove the top block from the
@@ -431,82 +431,82 @@ bool Blockchain::deinit()
// from it to the tx_pool
block Blockchain::pop_block_from_blockchain()
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
-
- m_timestamps_and_difficulties_height = 0;
-
- block popped_block;
- std::vector<transaction> popped_txs;
-
- try
- {
- m_db->pop_block(popped_block, popped_txs);
- }
- // anything that could cause this to throw is likely catastrophic,
- // so we re-throw
- catch (const std::exception& e)
- {
- LOG_ERROR("Error popping block from blockchain: " << e.what());
- throw;
- }
- catch (...)
- {
- LOG_ERROR("Error popping block from blockchain, throwing!");
- throw;
- }
-
- // return transactions from popped block to the tx_pool
- for (transaction& tx : popped_txs)
- {
- if (!is_coinbase(tx))
- {
- cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
- // We assume that if they were in a block, the transactions are already
- // known to the network as a whole. However, if we had mined that block,
- // that might not be always true. Unlikely though, and always relaying
- // these again might cause a spike of traffic as many nodes re-relay
- // all the transactions in a popped block when a reorg happens.
- bool r = m_tx_pool.add_tx(tx, tvc, true, true);
- if (!r)
- {
- LOG_ERROR("Error returning transaction to tx_pool");
- }
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+
+ m_timestamps_and_difficulties_height = 0;
+
+ block popped_block;
+ std::vector<transaction> popped_txs;
+
+ try
+ {
+ m_db->pop_block(popped_block, popped_txs);
+ }
+ // anything that could cause this to throw is likely catastrophic,
+ // so we re-throw
+ catch (const std::exception& e)
+ {
+ LOG_ERROR("Error popping block from blockchain: " << e.what());
+ throw;
+ }
+ catch (...)
+ {
+ LOG_ERROR("Error popping block from blockchain, throwing!");
+ throw;
+ }
+
+ // return transactions from popped block to the tx_pool
+ for (transaction& tx : popped_txs)
+ {
+ if (!is_coinbase(tx))
+ {
+ cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
+ // We assume that if they were in a block, the transactions are already
+ // known to the network as a whole. However, if we had mined that block,
+ // that might not be always true. Unlikely though, and always relaying
+ // these again might cause a spike of traffic as many nodes re-relay
+ // all the transactions in a popped block when a reorg happens.
+ bool r = m_tx_pool.add_tx(tx, tvc, true, true);
+ if (!r)
+ {
+ LOG_ERROR("Error returning transaction to tx_pool");
+ }
}
+ }
- return popped_block;
+ return popped_block;
}
//------------------------------------------------------------------
bool Blockchain::reset_and_set_genesis_block(const block& b)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- m_transactions.clear();
- m_blocks.clear();
- m_blocks_index.clear();
- m_alternative_chains.clear();
- m_outputs.clear();
- m_db->reset();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ m_transactions.clear();
+ m_blocks.clear();
+ m_blocks_index.clear();
+ m_alternative_chains.clear();
+ m_outputs.clear();
+ m_db->reset();
- block_verification_context bvc = boost::value_initialized<block_verification_context>();
- add_new_block(b, bvc);
- return bvc.m_added_to_main_chain && !bvc.m_verifivation_failed;
+ block_verification_context bvc = boost::value_initialized<block_verification_context>();
+ add_new_block(b, bvc);
+ return bvc.m_added_to_main_chain && !bvc.m_verifivation_failed;
}
//------------------------------------------------------------------
crypto::hash Blockchain::get_tail_id(uint64_t& height) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- height = m_db->height() - 1;
- return get_tail_id();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ height = m_db->height() - 1;
+ return get_tail_id();
}
//------------------------------------------------------------------
crypto::hash Blockchain::get_tail_id() const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- return m_db->top_block_hash();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ return m_db->top_block_hash();
}
//------------------------------------------------------------------
/*TODO: this function was...poorly written. As such, I'm not entirely
@@ -523,120 +523,120 @@ crypto::hash Blockchain::get_tail_id() const
*/
bool Blockchain::get_short_chain_history(std::list<crypto::hash>& ids) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- uint64_t i = 0;
- uint64_t current_multiplier = 1;
- uint64_t sz = m_db->height();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ uint64_t i = 0;
+ uint64_t current_multiplier = 1;
+ uint64_t sz = m_db->height();
- if(!sz)
- return true;
+ if(!sz)
+ return true;
- bool genesis_included = false;
- uint64_t current_back_offset = 1;
- while(current_back_offset < sz)
- {
- ids.push_back(m_db->get_block_hash_from_height(sz - current_back_offset));
+ bool genesis_included = false;
+ uint64_t current_back_offset = 1;
+ while(current_back_offset < sz)
+ {
+ ids.push_back(m_db->get_block_hash_from_height(sz - current_back_offset));
- if(sz-current_back_offset == 0)
- {
- genesis_included = true;
- }
- if(i < 10)
- {
- ++current_back_offset;
- }
- else
- {
- current_multiplier *= 2;
- current_back_offset += current_multiplier;
- }
- ++i;
+ if(sz-current_back_offset == 0)
+ {
+ genesis_included = true;
}
-
- if (!genesis_included)
+ if(i < 10)
+ {
+ ++current_back_offset;
+ }
+ else
{
- ids.push_back(m_db->get_block_hash_from_height(0));
+ current_multiplier *= 2;
+ current_back_offset += current_multiplier;
}
+ ++i;
+ }
- return true;
+ if (!genesis_included)
+ {
+ ids.push_back(m_db->get_block_hash_from_height(0));
+ }
+
+ return true;
}
//------------------------------------------------------------------
crypto::hash Blockchain::get_block_id_by_height(uint64_t height) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- try
- {
- return m_db->get_block_hash_from_height(height);
- }
- catch (const BLOCK_DNE& e)
- {
- }
- catch (const std::exception& e)
- {
- LOG_PRINT_L0(std::string("Something went wrong fetching block hash by height: ") + e.what());
- throw;
- }
- catch (...)
- {
- LOG_PRINT_L0(std::string("Something went wrong fetching block hash by height"));
- throw;
- }
- return null_hash;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ try
+ {
+ return m_db->get_block_hash_from_height(height);
+ }
+ catch (const BLOCK_DNE& e)
+ {
+ }
+ catch (const std::exception& e)
+ {
+ LOG_PRINT_L0(std::string("Something went wrong fetching block hash by height: ") + e.what());
+ throw;
+ }
+ catch (...)
+ {
+ LOG_PRINT_L0(std::string("Something went wrong fetching block hash by height"));
+ throw;
+ }
+ return null_hash;
}
//------------------------------------------------------------------
bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- // try to find block in main chain
- try
- {
- blk = m_db->get_block(h);
- return true;
- }
- // try to find block in alternative chain
- catch (const BLOCK_DNE& e)
- {
- blocks_ext_by_hash::const_iterator it_alt = m_alternative_chains.find(h);
- if (m_alternative_chains.end() != it_alt)
- {
- blk = it_alt->second.bl;
- return true;
- }
- }
- catch (const std::exception& e)
- {
- LOG_PRINT_L0(std::string("Something went wrong fetching block by hash: ") + e.what());
- throw;
- }
- catch (...)
- {
- LOG_PRINT_L0(std::string("Something went wrong fetching block hash by hash"));
- throw;
- }
-
- return false;
+ // try to find block in main chain
+ try
+ {
+ blk = m_db->get_block(h);
+ return true;
+ }
+ // try to find block in alternative chain
+ catch (const BLOCK_DNE& e)
+ {
+ blocks_ext_by_hash::const_iterator it_alt = m_alternative_chains.find(h);
+ if (m_alternative_chains.end() != it_alt)
+ {
+ blk = it_alt->second.bl;
+ return true;
+ }
+ }
+ catch (const std::exception& e)
+ {
+ LOG_PRINT_L0(std::string("Something went wrong fetching block by hash: ") + e.what());
+ throw;
+ }
+ catch (...)
+ {
+ LOG_PRINT_L0(std::string("Something went wrong fetching block hash by hash"));
+ throw;
+ }
+
+ return false;
}
//------------------------------------------------------------------
//FIXME: this function does not seem to be called from anywhere, but
// if it ever is, should probably change std::list for std::vector
void Blockchain::get_all_known_block_ids(std::list<crypto::hash> &main, std::list<crypto::hash> &alt, std::list<crypto::hash> &invalid) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- for (auto& a : m_db->get_hashes_range(0, m_db->height() - 1))
- {
- main.push_back(a);
- }
+ for (auto& a : m_db->get_hashes_range(0, m_db->height() - 1))
+ {
+ main.push_back(a);
+ }
- BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_alternative_chains)
+ BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_alternative_chains)
alt.push_back(v.first);
- BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_invalid_blocks)
+ BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_invalid_blocks)
invalid.push_back(v.first);
}
//------------------------------------------------------------------
@@ -646,51 +646,51 @@ void Blockchain::get_all_known_block_ids(std::list<crypto::hash> &main, std::lis
// less blocks than desired if there aren't enough.
difficulty_type Blockchain::get_difficulty_for_next_block()
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- std::vector<uint64_t> timestamps;
- std::vector<difficulty_type> difficulties;
- auto height = m_db->height();
- // ND: Speedup
- // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
- // then when the next block difficulty is queried, push the latest height data and
- // pop the oldest one from the list. This only requires 1x read per height instead
- // of doing 735 (DIFFICULTY_BLOCKS_COUNT).
- if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1))
- {
- uint64_t index = height - 1;
- m_timestamps.push_back(m_db->get_block_timestamp(index));
- m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
-
- while (m_timestamps.size() > DIFFICULTY_BLOCKS_COUNT)
- m_timestamps.erase(m_timestamps.begin());
- while (m_difficulties.size() > DIFFICULTY_BLOCKS_COUNT)
- m_difficulties.erase(m_difficulties.begin());
-
- m_timestamps_and_difficulties_height = height;
- timestamps = m_timestamps;
- difficulties = m_difficulties;
- }
- else
- {
- size_t offset = height - std::min < size_t > (height, static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
- if (offset == 0)
- ++offset;
-
- timestamps.clear();
- difficulties.clear();
- for (; offset < height; offset++)
- {
- timestamps.push_back(m_db->get_block_timestamp(offset));
- difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
- }
-
- m_timestamps_and_difficulties_height = height;
- m_timestamps = timestamps;
- m_difficulties = difficulties;
- }
- size_t target = get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET;
- return next_difficulty(timestamps, difficulties, target);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ std::vector<uint64_t> timestamps;
+ std::vector<difficulty_type> difficulties;
+ auto height = m_db->height();
+ // ND: Speedup
+ // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
+ // then when the next block difficulty is queried, push the latest height data and
+ // pop the oldest one from the list. This only requires 1x read per height instead
+ // of doing 735 (DIFFICULTY_BLOCKS_COUNT).
+ if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1))
+ {
+ uint64_t index = height - 1;
+ m_timestamps.push_back(m_db->get_block_timestamp(index));
+ m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
+
+ while (m_timestamps.size() > DIFFICULTY_BLOCKS_COUNT)
+ m_timestamps.erase(m_timestamps.begin());
+ while (m_difficulties.size() > DIFFICULTY_BLOCKS_COUNT)
+ m_difficulties.erase(m_difficulties.begin());
+
+ m_timestamps_and_difficulties_height = height;
+ timestamps = m_timestamps;
+ difficulties = m_difficulties;
+ }
+ else
+ {
+ size_t offset = height - std::min < size_t > (height, static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
+ if (offset == 0)
+ ++offset;
+
+ timestamps.clear();
+ difficulties.clear();
+ for (; offset < height; offset++)
+ {
+ timestamps.push_back(m_db->get_block_timestamp(offset));
+ difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
+ }
+
+ m_timestamps_and_difficulties_height = height;
+ m_timestamps = timestamps;
+ m_difficulties = difficulties;
+ }
+ size_t target = get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET;
+ return next_difficulty(timestamps, difficulties, target);
}
//------------------------------------------------------------------
// This function removes blocks from the blockchain until it gets to the
@@ -698,193 +698,193 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
// that had been removed.
bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain, uint64_t rollback_height)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- m_timestamps_and_difficulties_height = 0;
+ m_timestamps_and_difficulties_height = 0;
- // remove blocks from blockchain until we get back to where we should be.
- while (m_db->height() != rollback_height)
- {
- pop_block_from_blockchain();
- }
+ // remove blocks from blockchain until we get back to where we should be.
+ while (m_db->height() != rollback_height)
+ {
+ pop_block_from_blockchain();
+ }
- //return back original chain
- for (auto& bl : original_chain)
- {
- block_verification_context bvc = boost::value_initialized<block_verification_context>();
- bool r = handle_block_to_main_chain(bl, bvc);
- CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain, false, "PANIC! failed to add (again) block while chain switching during the rollback!");
- }
+ //return back original chain
+ for (auto& bl : original_chain)
+ {
+ block_verification_context bvc = boost::value_initialized<block_verification_context>();
+ bool r = handle_block_to_main_chain(bl, bvc);
+ CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain, false, "PANIC! failed to add (again) block while chain switching during the rollback!");
+ }
- m_hardfork->reorganize_from_chain_height(rollback_height);
+ m_hardfork->reorganize_from_chain_height(rollback_height);
- LOG_PRINT_L1("Rollback to height " << rollback_height << " was successful.");
- if (original_chain.size())
- {
- LOG_PRINT_L1("Restoration to previous blockchain successful as well.");
- }
- return true;
+ LOG_PRINT_L1("Rollback to height " << rollback_height << " was successful.");
+ if (original_chain.size())
+ {
+ LOG_PRINT_L1("Restoration to previous blockchain successful as well.");
+ }
+ return true;
}
//------------------------------------------------------------------
// This function attempts to switch to an alternate chain, returning
// boolean based on success therein.
bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain, bool discard_disconnected_chain)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- m_timestamps_and_difficulties_height = 0;
+ m_timestamps_and_difficulties_height = 0;
- // if empty alt chain passed (not sure how that could happen), return false
- CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
-
- // verify that main chain has front of alt chain's parent block
- if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
- {
- LOG_ERROR("Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain!");
- return false;
- }
+ // if empty alt chain passed (not sure how that could happen), return false
+ CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
- // pop blocks from the blockchain until the top block is the parent
- // of the front block of the alt chain.
- std::list<block> disconnected_chain;
- while (m_db->top_block_hash() != alt_chain.front()->second.bl.prev_id)
- {
- block b = pop_block_from_blockchain();
- disconnected_chain.push_front(b);
- }
+ // verify that main chain has front of alt chain's parent block
+ if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
+ {
+ LOG_ERROR("Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain!");
+ return false;
+ }
+
+ // pop blocks from the blockchain until the top block is the parent
+ // of the front block of the alt chain.
+ std::list<block> disconnected_chain;
+ while (m_db->top_block_hash() != alt_chain.front()->second.bl.prev_id)
+ {
+ block b = pop_block_from_blockchain();
+ disconnected_chain.push_front(b);
+ }
+
+ auto split_height = m_db->height();
+
+ //connecting new alternative chain
+ for(auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++)
+ {
+ auto ch_ent = *alt_ch_iter;
+ block_verification_context bvc = boost::value_initialized<block_verification_context>();
- auto split_height = m_db->height();
+ // add block to main chain
+ bool r = handle_block_to_main_chain(ch_ent->second.bl, bvc);
- //connecting new alternative chain
- for(auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++)
+ // if adding block to main chain failed, rollback to previous state and
+ // return false
+ if(!r || !bvc.m_added_to_main_chain)
{
- auto ch_ent = *alt_ch_iter;
- block_verification_context bvc = boost::value_initialized<block_verification_context>();
-
- // add block to main chain
- bool r = handle_block_to_main_chain(ch_ent->second.bl, bvc);
-
- // if adding block to main chain failed, rollback to previous state and
- // return false
- if(!r || !bvc.m_added_to_main_chain)
- {
- LOG_PRINT_L1("Failed to switch to alternative blockchain");
+ LOG_PRINT_L1("Failed to switch to alternative blockchain");
- // rollback_blockchain_switching should be moved to two different
- // functions: rollback and apply_chain, but for now we pretend it is
- // just the latter (because the rollback was done above).
- rollback_blockchain_switching(disconnected_chain, m_db->height());
+ // rollback_blockchain_switching should be moved to two different
+ // functions: rollback and apply_chain, but for now we pretend it is
+ // just the latter (because the rollback was done above).
+ rollback_blockchain_switching(disconnected_chain, m_db->height());
- // FIXME: Why do we keep invalid blocks around? Possibly in case we hear
- // about them again so we can immediately dismiss them, but needs some
- // looking into.
- add_block_as_invalid(ch_ent->second, get_block_hash(ch_ent->second.bl));
- LOG_PRINT_L1("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl));
- m_alternative_chains.erase(ch_ent);
+ // FIXME: Why do we keep invalid blocks around? Possibly in case we hear
+ // about them again so we can immediately dismiss them, but needs some
+ // looking into.
+ add_block_as_invalid(ch_ent->second, get_block_hash(ch_ent->second.bl));
+ LOG_PRINT_L1("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl));
+ m_alternative_chains.erase(ch_ent);
- for(auto alt_ch_to_orph_iter = ++alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); alt_ch_to_orph_iter++)
- {
- add_block_as_invalid((*alt_ch_iter)->second, (*alt_ch_iter)->first);
- m_alternative_chains.erase(*alt_ch_to_orph_iter);
- }
- return false;
- }
- }
-
- // if we're to keep the disconnected blocks, add them as alternates
- if(!discard_disconnected_chain)
- {
- //pushing old chain as alternative chain
- for (auto& old_ch_ent : disconnected_chain)
- {
- block_verification_context bvc = boost::value_initialized<block_verification_context>();
- bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
- if(!r)
- {
- LOG_PRINT_L1("Failed to push ex-main chain blocks to alternative chain ");
- // previously this would fail the blockchain switching, but I don't
- // think this is bad enough to warrant that.
- }
- }
+ for(auto alt_ch_to_orph_iter = ++alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); alt_ch_to_orph_iter++)
+ {
+ add_block_as_invalid((*alt_ch_iter)->second, (*alt_ch_iter)->first);
+ m_alternative_chains.erase(*alt_ch_to_orph_iter);
+ }
+ return false;
+ }
+ }
+
+ // if we're to keep the disconnected blocks, add them as alternates
+ if(!discard_disconnected_chain)
+ {
+ //pushing old chain as alternative chain
+ for (auto& old_ch_ent : disconnected_chain)
+ {
+ block_verification_context bvc = boost::value_initialized<block_verification_context>();
+ bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
+ if(!r)
+ {
+ LOG_PRINT_L1("Failed to push ex-main chain blocks to alternative chain ");
+ // previously this would fail the blockchain switching, but I don't
+ // think this is bad enough to warrant that.
+ }
}
+ }
- //removing alt_chain entries from alternative chain
- BOOST_FOREACH(auto ch_ent, alt_chain)
- {
- m_alternative_chains.erase(ch_ent);
- }
+ //removing alt_chain entries from alternative chain
+ BOOST_FOREACH(auto ch_ent, alt_chain)
+ {
+ m_alternative_chains.erase(ch_ent);
+ }
- m_hardfork->reorganize_from_chain_height(split_height);
+ m_hardfork->reorganize_from_chain_height(split_height);
- LOG_PRINT_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height(), LOG_LEVEL_0);
- return true;
+ LOG_PRINT_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height(), LOG_LEVEL_0);
+ return true;
}
//------------------------------------------------------------------
// This function calculates the difficulty target for the block being added to
// an alternate chain.
difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std::list<blocks_ext_by_hash::iterator>& alt_chain, block_extended_info& bei) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- std::vector<uint64_t> timestamps;
- std::vector<difficulty_type> cumulative_difficulties;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ std::vector<uint64_t> timestamps;
+ std::vector<difficulty_type> cumulative_difficulties;
- // if the alt chain isn't long enough to calculate the difficulty target
- // based on its blocks alone, need to get more blocks from the main chain
- if(alt_chain.size()< DIFFICULTY_BLOCKS_COUNT)
- {
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ // if the alt chain isn't long enough to calculate the difficulty target
+ // based on its blocks alone, need to get more blocks from the main chain
+ if(alt_chain.size()< DIFFICULTY_BLOCKS_COUNT)
+ {
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- // Figure out start and stop offsets for main chain blocks
- size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front()->second.height : bei.height;
- size_t main_chain_count = DIFFICULTY_BLOCKS_COUNT - std::min(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT), alt_chain.size());
- main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
- size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
+ // Figure out start and stop offsets for main chain blocks
+ size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front()->second.height : bei.height;
+ size_t main_chain_count = DIFFICULTY_BLOCKS_COUNT - std::min(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT), alt_chain.size());
+ main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
+ size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
- if(!main_chain_start_offset)
- ++main_chain_start_offset; //skip genesis block
+ if(!main_chain_start_offset)
+ ++main_chain_start_offset; //skip genesis block
- // get difficulties and timestamps from relevant main chain blocks
- for(; main_chain_start_offset < main_chain_stop_offset; ++main_chain_start_offset)
- {
- timestamps.push_back(m_db->get_block_timestamp(main_chain_start_offset));
- cumulative_difficulties.push_back(m_db->get_block_cumulative_difficulty(main_chain_start_offset));
- }
+ // get difficulties and timestamps from relevant main chain blocks
+ for(; main_chain_start_offset < main_chain_stop_offset; ++main_chain_start_offset)
+ {
+ timestamps.push_back(m_db->get_block_timestamp(main_chain_start_offset));
+ cumulative_difficulties.push_back(m_db->get_block_cumulative_difficulty(main_chain_start_offset));
+ }
- // make sure we haven't accidentally grabbed too many blocks...maybe don't need this check?
- CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= DIFFICULTY_BLOCKS_COUNT, false, "Internal error, alt_chain.size()[" << alt_chain.size() << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << DIFFICULTY_BLOCKS_COUNT);
+ // make sure we haven't accidentally grabbed too many blocks...maybe don't need this check?
+ CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= DIFFICULTY_BLOCKS_COUNT, false, "Internal error, alt_chain.size()[" << alt_chain.size() << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << DIFFICULTY_BLOCKS_COUNT);
- for (auto it : alt_chain)
- {
- timestamps.push_back(it->second.bl.timestamp);
- cumulative_difficulties.push_back(it->second.cumulative_difficulty);
- }
+ for (auto it : alt_chain)
+ {
+ timestamps.push_back(it->second.bl.timestamp);
+ cumulative_difficulties.push_back(it->second.cumulative_difficulty);
}
- // if the alt chain is long enough for the difficulty calc, grab difficulties
- // and timestamps from it alone
- else
+ }
+ // if the alt chain is long enough for the difficulty calc, grab difficulties
+ // and timestamps from it alone
+ else
+ {
+ timestamps.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
+ cumulative_difficulties.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
+ size_t count = 0;
+ size_t max_i = timestamps.size()-1;
+ // get difficulties and timestamps from most recent blocks in alt chain
+ BOOST_REVERSE_FOREACH(auto it, alt_chain)
{
- timestamps.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
- cumulative_difficulties.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
- size_t count = 0;
- size_t max_i = timestamps.size()-1;
- // get difficulties and timestamps from most recent blocks in alt chain
- BOOST_REVERSE_FOREACH(auto it, alt_chain)
- {
- timestamps[max_i - count] = it->second.bl.timestamp;
- cumulative_difficulties[max_i - count] = it->second.cumulative_difficulty;
- count++;
- if(count >= DIFFICULTY_BLOCKS_COUNT)
- break;
- }
+ timestamps[max_i - count] = it->second.bl.timestamp;
+ cumulative_difficulties[max_i - count] = it->second.cumulative_difficulty;
+ count++;
+ if(count >= DIFFICULTY_BLOCKS_COUNT)
+ break;
}
+ }
- // FIXME: This will fail if fork activation heights are subject to voting
- size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET;
+ // FIXME: This will fail if fork activation heights are subject to voting
+ size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET;
- // calculate the difficulty target for the block and return it
- return next_difficulty(timestamps, cumulative_difficulties, target);
+ // calculate the difficulty target for the block and return it
+ return next_difficulty(timestamps, cumulative_difficulties, target);
}
//------------------------------------------------------------------
// This function does a sanity check on basic things that all miner
@@ -894,94 +894,94 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// a non-overflowing tx amount (dubious necessity on this check)
bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs");
- CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
- if(boost::get<txin_gen>(b.miner_tx.vin[0]).height != height)
- {
- LOG_PRINT_RED_L1("The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.miner_tx.vin[0]).height << ", expected: " << height);
- return false;
- }
- CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
-
- //check outs overflow
- //NOTE: not entirely sure this is necessary, given that this function is
- // designed simply to make sure the total amount for a transaction
- // does not overflow a uint64_t, and this transaction *is* a uint64_t...
- if(!check_outs_overflow(b.miner_tx))
- {
- LOG_PRINT_RED_L1("miner transaction has money overflow in block " << get_block_hash(b));
- return false;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs");
+ CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
+ if(boost::get<txin_gen>(b.miner_tx.vin[0]).height != height)
+ {
+ LOG_PRINT_RED_L1("The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.miner_tx.vin[0]).height << ", expected: " << height);
+ return false;
+ }
+ CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
+
+ //check outs overflow
+ //NOTE: not entirely sure this is necessary, given that this function is
+ // designed simply to make sure the total amount for a transaction
+ // does not overflow a uint64_t, and this transaction *is* a uint64_t...
+ if(!check_outs_overflow(b.miner_tx))
+ {
+ LOG_PRINT_RED_L1("miner transaction has money overflow in block " << get_block_hash(b));
+ return false;
+ }
- return true;
+ return true;
}
//------------------------------------------------------------------
// This function validates the miner transaction reward
bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_block_size, uint64_t fee, uint64_t& base_reward, uint64_t already_generated_coins)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- //validate reward
- uint64_t money_in_use = 0;
- BOOST_FOREACH(auto& o, b.miner_tx.vout)
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ //validate reward
+ uint64_t money_in_use = 0;
+ BOOST_FOREACH(auto& o, b.miner_tx.vout)
money_in_use += o.amount;
- std::vector<size_t> last_blocks_sizes;
- get_last_n_blocks_sizes(last_blocks_sizes, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
- if (!get_block_reward(epee::misc_utils::median(last_blocks_sizes), cumulative_block_size, already_generated_coins, base_reward, get_current_hard_fork_version()))
- {
- LOG_PRINT_L1("block size " << cumulative_block_size << " is bigger than allowed for this blockchain");
- return false;
- }
- if(base_reward + fee < money_in_use)
- {
- LOG_PRINT_L1("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << ")");
- return false;
- }
- // From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
- if (m_hardfork->get_current_version() < 2)
- {
- if(base_reward + fee != money_in_use)
- {
- LOG_PRINT_L1("coinbase transaction doesn't use full amount of block reward: spent: " << money_in_use << ", block reward " << base_reward + fee << "(" << base_reward << "+" << fee << ")");
- return false;
- }
- }
- else
- {
- // from hard fork 2, since a miner can claim less than the full block reward, we update the base_reward
- // to show the amount of coins that were actually generated, the remainder will be pushed back for later
- // emission. This modifies the emission curve very slightly.
- CHECK_AND_ASSERT_MES(money_in_use - fee <= base_reward, false, "base reward calculation bug");
- base_reward = money_in_use - fee;
- }
- return true;
+ std::vector<size_t> last_blocks_sizes;
+ get_last_n_blocks_sizes(last_blocks_sizes, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
+ if (!get_block_reward(epee::misc_utils::median(last_blocks_sizes), cumulative_block_size, already_generated_coins, base_reward, get_current_hard_fork_version()))
+ {
+ LOG_PRINT_L1("block size " << cumulative_block_size << " is bigger than allowed for this blockchain");
+ return false;
+ }
+ if(base_reward + fee < money_in_use)
+ {
+ LOG_PRINT_L1("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << ")");
+ return false;
+ }
+ // From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
+ if (m_hardfork->get_current_version() < 2)
+ {
+ if(base_reward + fee != money_in_use)
+ {
+ LOG_PRINT_L1("coinbase transaction doesn't use full amount of block reward: spent: " << money_in_use << ", block reward " << base_reward + fee << "(" << base_reward << "+" << fee << ")");
+ return false;
+ }
+ }
+ else
+ {
+ // from hard fork 2, since a miner can claim less than the full block reward, we update the base_reward
+ // to show the amount of coins that were actually generated, the remainder will be pushed back for later
+ // emission. This modifies the emission curve very slightly.
+ CHECK_AND_ASSERT_MES(money_in_use - fee <= base_reward, false, "base reward calculation bug");
+ base_reward = money_in_use - fee;
+ }
+ return true;
}
//------------------------------------------------------------------
// get the block sizes of the last <count> blocks, starting at <from_height>
// and return by reference <sz>.
void Blockchain::get_last_n_blocks_sizes(std::vector<size_t>& sz, size_t count) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- auto h = m_db->height();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ auto h = m_db->height();
- // this function is meaningless for an empty blockchain...granted it should never be empty
- if(h == 0)
- return;
+ // this function is meaningless for an empty blockchain...granted it should never be empty
+ if(h == 0)
+ return;
- // add size of last <count> blocks to vector <sz> (or less, if blockchain size < count)
- size_t start_offset = h - std::min<size_t>(h, count);
- for(size_t i = start_offset; i < h; i++)
- {
- sz.push_back(m_db->get_block_size(i));
- }
+ // add size of last <count> blocks to vector <sz> (or less, if blockchain size < count)
+ size_t start_offset = h - std::min<size_t>(h, count);
+ for(size_t i = start_offset; i < h; i++)
+ {
+ sz.push_back(m_db->get_block_size(i));
+ }
}
//------------------------------------------------------------------
uint64_t Blockchain::get_current_cumulative_blocksize_limit() const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- return m_current_block_cumul_sz_limit;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ return m_current_block_cumul_sz_limit;
}
//------------------------------------------------------------------
//TODO: This function only needed minor modification to work with BlockchainDB,
@@ -997,159 +997,159 @@ uint64_t Blockchain::get_current_cumulative_blocksize_limit() const
// necessary at all.
bool Blockchain::create_block_template(block& b, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- size_t median_size;
- uint64_t already_generated_coins;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ size_t median_size;
+ uint64_t already_generated_coins;
- CRITICAL_REGION_BEGIN(m_blockchain_lock);
- height = m_db->height();
+ CRITICAL_REGION_BEGIN(m_blockchain_lock);
+ height = m_db->height();
- b.major_version = m_hardfork->get_current_version();
- b.minor_version = m_hardfork->get_ideal_version();
- b.prev_id = get_tail_id();
- b.timestamp = time(NULL);
+ b.major_version = m_hardfork->get_current_version();
+ b.minor_version = m_hardfork->get_ideal_version();
+ b.prev_id = get_tail_id();
+ b.timestamp = time(NULL);
- diffic = get_difficulty_for_next_block();
- CHECK_AND_ASSERT_MES(diffic, false, "difficulty owverhead.");
+ diffic = get_difficulty_for_next_block();
+ CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead.");
- median_size = m_current_block_cumul_sz_limit / 2;
- already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
+ median_size = m_current_block_cumul_sz_limit / 2;
+ already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
- CRITICAL_REGION_END();
+ CRITICAL_REGION_END();
- size_t txs_size;
- uint64_t fee;
- if (!m_tx_pool.fill_block_template(b, median_size, already_generated_coins, txs_size, fee))
- {
- return false;
- }
+ size_t txs_size;
+ uint64_t fee;
+ if (!m_tx_pool.fill_block_template(b, median_size, already_generated_coins, txs_size, fee))
+ {
+ return false;
+ }
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
- size_t real_txs_size = 0;
- uint64_t real_fee = 0;
- CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock);
- BOOST_FOREACH(crypto::hash &cur_hash, b.tx_hashes)
- {
- auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
- if (cur_res == m_tx_pool.m_transactions.end())
- {
- LOG_ERROR("Creating block template: error: transaction not found");
- continue;
- }
- tx_memory_pool::tx_details &cur_tx = cur_res->second;
- real_txs_size += cur_tx.blob_size;
- real_fee += cur_tx.fee;
- if (cur_tx.blob_size != get_object_blobsize(cur_tx.tx))
- {
- LOG_ERROR("Creating block template: error: invalid transaction size");
- }
- uint64_t inputs_amount;
- if (!get_inputs_money_amount(cur_tx.tx, inputs_amount))
- {
- LOG_ERROR("Creating block template: error: cannot get inputs amount");
- }
- else if (cur_tx.fee != inputs_amount - get_outs_money_amount(cur_tx.tx))
- {
- LOG_ERROR("Creating block template: error: invalid fee");
- }
- }
- if (txs_size != real_txs_size)
- {
- LOG_ERROR("Creating block template: error: wrongly calculated transaction size");
- }
- if (fee != real_fee)
- {
- LOG_ERROR("Creating block template: error: wrongly calculated fee");
- }
- CRITICAL_REGION_END();
- LOG_PRINT_L1("Creating block template: height " << height <<
- ", median size " << median_size <<
- ", already generated coins " << already_generated_coins <<
- ", transaction size " << txs_size <<
- ", fee " << fee);
+ size_t real_txs_size = 0;
+ uint64_t real_fee = 0;
+ CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock);
+ BOOST_FOREACH(crypto::hash &cur_hash, b.tx_hashes)
+ {
+ auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
+ if (cur_res == m_tx_pool.m_transactions.end())
+ {
+ LOG_ERROR("Creating block template: error: transaction not found");
+ continue;
+ }
+ tx_memory_pool::tx_details &cur_tx = cur_res->second;
+ real_txs_size += cur_tx.blob_size;
+ real_fee += cur_tx.fee;
+ if (cur_tx.blob_size != get_object_blobsize(cur_tx.tx))
+ {
+ LOG_ERROR("Creating block template: error: invalid transaction size");
+ }
+ uint64_t inputs_amount;
+ if (!get_inputs_money_amount(cur_tx.tx, inputs_amount))
+ {
+ LOG_ERROR("Creating block template: error: cannot get inputs amount");
+ }
+ else if (cur_tx.fee != inputs_amount - get_outs_money_amount(cur_tx.tx))
+ {
+ LOG_ERROR("Creating block template: error: invalid fee");
+ }
+ }
+ if (txs_size != real_txs_size)
+ {
+ LOG_ERROR("Creating block template: error: wrongly calculated transaction size");
+ }
+ if (fee != real_fee)
+ {
+ LOG_ERROR("Creating block template: error: wrongly calculated fee");
+ }
+ CRITICAL_REGION_END();
+ LOG_PRINT_L1("Creating block template: height " << height <<
+ ", median size " << median_size <<
+ ", already generated coins " << already_generated_coins <<
+ ", transaction size " << txs_size <<
+ ", fee " << fee);
#endif
- /*
- two-phase miner transaction generation: we don't know exact block size until we prepare block, but we don't know reward until we know
- block size, so first miner transaction generated with fake amount of money, and with phase we know think we know expected block size
- */
- //make blocks coin-base tx looks close to real coinbase tx to get truthful blob size
- bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, 11, m_hardfork->get_current_version());
- CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance");
- size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx);
+ /*
+ two-phase miner transaction generation: we don't know exact block size until we prepare block, but we don't know reward until we know
+ block size, so first miner transaction generated with fake amount of money, and with phase we know think we know expected block size
+ */
+ //make blocks coin-base tx looks close to real coinbase tx to get truthful blob size
+ bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, 11, m_hardfork->get_current_version());
+ CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance");
+ size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx);
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
- LOG_PRINT_L1("Creating block template: miner tx size " << get_object_blobsize(b.miner_tx) <<
- ", cumulative size " << cumulative_size);
+ LOG_PRINT_L1("Creating block template: miner tx size " << get_object_blobsize(b.miner_tx) <<
+ ", cumulative size " << cumulative_size);
#endif
- for (size_t try_count = 0; try_count != 10; ++try_count)
- {
- r = construct_miner_tx(height, median_size, already_generated_coins, cumulative_size, fee, miner_address, b.miner_tx, ex_nonce, 11, m_hardfork->get_current_version());
+ for (size_t try_count = 0; try_count != 10; ++try_count)
+ {
+ r = construct_miner_tx(height, median_size, already_generated_coins, cumulative_size, fee, miner_address, b.miner_tx, ex_nonce, 11, m_hardfork->get_current_version());
- CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, second chance");
- size_t coinbase_blob_size = get_object_blobsize(b.miner_tx);
- if (coinbase_blob_size > cumulative_size - txs_size)
- {
- cumulative_size = txs_size + coinbase_blob_size;
+ CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, second chance");
+ size_t coinbase_blob_size = get_object_blobsize(b.miner_tx);
+ if (coinbase_blob_size > cumulative_size - txs_size)
+ {
+ cumulative_size = txs_size + coinbase_blob_size;
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
- LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
- ", cumulative size " << cumulative_size << " is greater then before");
+ LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
+ ", cumulative size " << cumulative_size << " is greater then before");
#endif
- continue;
- }
+ continue;
+ }
- if (coinbase_blob_size < cumulative_size - txs_size)
- {
- size_t delta = cumulative_size - txs_size - coinbase_blob_size;
+ if (coinbase_blob_size < cumulative_size - txs_size)
+ {
+ size_t delta = cumulative_size - txs_size - coinbase_blob_size;
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
- LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
- ", cumulative size " << txs_size + coinbase_blob_size <<
- " is less then before, adding " << delta << " zero bytes");
+ LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
+ ", cumulative size " << txs_size + coinbase_blob_size <<
+ " is less then before, adding " << delta << " zero bytes");
#endif
- b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0);
- //here could be 1 byte difference, because of extra field counter is varint, and it can become from 1-byte len to 2-bytes len.
- if (cumulative_size != txs_size + get_object_blobsize(b.miner_tx))
- {
- CHECK_AND_ASSERT_MES(cumulative_size + 1 == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " + 1 is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx));
- b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1);
- if (cumulative_size != txs_size + get_object_blobsize(b.miner_tx))
- {
- //fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size
- LOG_PRINT_RED("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1 , LOG_LEVEL_2);
- cumulative_size += delta - 1;
- continue;
- }
- LOG_PRINT_GREEN("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count, LOG_LEVEL_1);
- }
- }
- CHECK_AND_ASSERT_MES(cumulative_size == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx));
+ b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0);
+ //here could be 1 byte difference, because of extra field counter is varint, and it can become from 1-byte len to 2-bytes len.
+ if (cumulative_size != txs_size + get_object_blobsize(b.miner_tx))
+ {
+ CHECK_AND_ASSERT_MES(cumulative_size + 1 == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " + 1 is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx));
+ b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1);
+ if (cumulative_size != txs_size + get_object_blobsize(b.miner_tx))
+ {
+ //fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size
+ LOG_PRINT_RED("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1 , LOG_LEVEL_2);
+ cumulative_size += delta - 1;
+ continue;
+ }
+ LOG_PRINT_GREEN("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count, LOG_LEVEL_1);
+ }
+ }
+ CHECK_AND_ASSERT_MES(cumulative_size == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx));
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
- LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
- ", cumulative size " << cumulative_size << " is now good");
+ LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
+ ", cumulative size " << cumulative_size << " is now good");
#endif
- return true;
- }
- LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
- return false;
+ return true;
+ }
+ LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
+ return false;
}
//------------------------------------------------------------------
// for an alternate chain, get the timestamps from the main chain to complete
// the needed number of timestamps for the BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW.
bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vector<uint64_t>& timestamps)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
-
- if(timestamps.size() >= BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
- return true;
+ LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- size_t need_elements = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW - timestamps.size();
- CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " << " m_db->height() -- " << start_top_height << " >= " << m_db->height());
- size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
- while (start_top_height != stop_offset)
- {
- timestamps.push_back(m_db->get_block_timestamp(start_top_height));
- --start_top_height;
- }
+ if(timestamps.size() >= BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
return true;
+
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ size_t need_elements = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW - timestamps.size();
+ CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " << " m_db->height() -- " << start_top_height << " >= " << m_db->height());
+ size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
+ while (start_top_height != stop_offset)
+ {
+ timestamps.push_back(m_db->get_block_timestamp(start_top_height));
+ --start_top_height;
+ }
+ return true;
}
//------------------------------------------------------------------
// If a block is to be added and its parent block is not the current
@@ -1160,215 +1160,214 @@ bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vect
// a long forked chain eventually.
bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- m_timestamps_and_difficulties_height = 0;
- uint64_t block_height = get_block_height(b);
- if(0 == block_height)
- {
- LOG_PRINT_L1("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative), but miner tx says height is 0.");
- bvc.m_verifivation_failed = true;
- return false;
- }
- // this basically says if the blockchain is smaller than the first
- // checkpoint then alternate blocks are allowed. Alternatively, if the
- // last checkpoint *before* the end of the current chain is also before
- // the block to be added, then this is fine.
- if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height))
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ m_timestamps_and_difficulties_height = 0;
+ uint64_t block_height = get_block_height(b);
+ if(0 == block_height)
+ {
+ LOG_PRINT_L1("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative), but miner tx says height is 0.");
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+ // this basically says if the blockchain is smaller than the first
+ // checkpoint then alternate blocks are allowed. Alternatively, if the
+ // last checkpoint *before* the end of the current chain is also before
+ // the block to be added, then this is fine.
+ if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height))
+ {
+ LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " can't be accepted for alternative chain, block height: " << block_height << std::endl << " blockchain height: " << get_current_blockchain_height());
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+
+ //block is not related with head of main chain
+ //first of all - look in alternative chains container
+ auto it_prev = m_alternative_chains.find(b.prev_id);
+ bool parent_in_main = m_db->block_exists(b.prev_id);
+ if(it_prev != m_alternative_chains.end() || parent_in_main)
+ {
+ //we have new block in alternative chain
+
+ //build alternative subchain, front -> mainchain, back -> alternative head
+ blocks_ext_by_hash::iterator alt_it = it_prev; //m_alternative_chains.find()
+ std::list<blocks_ext_by_hash::iterator> alt_chain;
+ std::vector<uint64_t> timestamps;
+ while(alt_it != m_alternative_chains.end())
{
- LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " can't be accepted for alternative chain, block height: " << block_height << std::endl << " blockchain height: " << get_current_blockchain_height());
- bvc.m_verifivation_failed = true;
- return false;
+ alt_chain.push_front(alt_it);
+ timestamps.push_back(alt_it->second.bl.timestamp);
+ alt_it = m_alternative_chains.find(alt_it->second.bl.prev_id);
}
- //block is not related with head of main chain
- //first of all - look in alternative chains container
- auto it_prev = m_alternative_chains.find(b.prev_id);
- bool parent_in_main = m_db->block_exists(b.prev_id);
- if(it_prev != m_alternative_chains.end() || parent_in_main)
+ // if block to be added connects to known blocks that aren't part of the
+ // main chain -- that is, if we're adding on to an alternate chain
+ if(alt_chain.size())
{
- //we have new block in alternative chain
-
- //build alternative subchain, front -> mainchain, back -> alternative head
- blocks_ext_by_hash::iterator alt_it = it_prev; //m_alternative_chains.find()
- std::list<blocks_ext_by_hash::iterator> alt_chain;
- std::vector<uint64_t> timestamps;
- while(alt_it != m_alternative_chains.end())
- {
- alt_chain.push_front(alt_it);
- timestamps.push_back(alt_it->second.bl.timestamp);
- alt_it = m_alternative_chains.find(alt_it->second.bl.prev_id);
- }
-
- // if block to be added connects to known blocks that aren't part of the
- // main chain -- that is, if we're adding on to an alternate chain
- if(alt_chain.size())
- {
- // make sure alt chain doesn't somehow start past the end of the main chain
- CHECK_AND_ASSERT_MES(m_db->height() > alt_chain.front()->second.height, false, "main blockchain wrong height");
+ // make sure alt chain doesn't somehow start past the end of the main chain
+ CHECK_AND_ASSERT_MES(m_db->height() > alt_chain.front()->second.height, false, "main blockchain wrong height");
- // make sure that the blockchain contains the block that should connect
- // this alternate chain with it.
- if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
- {
- LOG_PRINT_L1("alternate chain does not appear to connect to main chain...");
- return false;
- }
+ // make sure that the blockchain contains the block that should connect
+ // this alternate chain with it.
+ if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
+ {
+ LOG_PRINT_L1("alternate chain does not appear to connect to main chain...");
+ return false;
+ }
- // make sure block connects correctly to the main chain
- auto h = m_db->get_block_hash_from_height(alt_chain.front()->second.height - 1);
- CHECK_AND_ASSERT_MES(h == alt_chain.front()->second.bl.prev_id, false, "alternative chain has wrong connection to main chain");
- complete_timestamps_vector(m_db->get_block_height(alt_chain.front()->second.bl.prev_id), timestamps);
- }
- // if block not associated with known alternate chain
- else
- {
- // if block parent is not part of main chain or an alternate chain,
- // we ignore it
- CHECK_AND_ASSERT_MES(parent_in_main, false, "internal error: broken imperative condition it_main_prev != m_blocks_index.end()");
+ // make sure block connects correctly to the main chain
+ auto h = m_db->get_block_hash_from_height(alt_chain.front()->second.height - 1);
+ CHECK_AND_ASSERT_MES(h == alt_chain.front()->second.bl.prev_id, false, "alternative chain has wrong connection to main chain");
+ complete_timestamps_vector(m_db->get_block_height(alt_chain.front()->second.bl.prev_id), timestamps);
+ }
+ // if block not associated with known alternate chain
+ else
+ {
+ // if block parent is not part of main chain or an alternate chain,
+ // we ignore it
+ CHECK_AND_ASSERT_MES(parent_in_main, false, "internal error: broken imperative condition it_main_prev != m_blocks_index.end()");
- complete_timestamps_vector(m_db->get_block_height(b.prev_id), timestamps);
- }
+ complete_timestamps_vector(m_db->get_block_height(b.prev_id), timestamps);
+ }
- // verify that the block's timestamp is within the acceptable range
- // (not earlier than the median of the last X blocks)
- if(!check_block_timestamp(timestamps, b))
- {
- LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " for alternative chain, has invalid timestamp: " << b.timestamp);
- bvc.m_verifivation_failed = true;
- return false;
- }
+ // verify that the block's timestamp is within the acceptable range
+ // (not earlier than the median of the last X blocks)
+ if(!check_block_timestamp(timestamps, b))
+ {
+ LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " for alternative chain, has invalid timestamp: " << b.timestamp);
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
- // FIXME: consider moving away from block_extended_info at some point
- block_extended_info bei = boost::value_initialized<block_extended_info>();
- bei.bl = b;
- bei.height = alt_chain.size() ? it_prev->second.height + 1 : m_db->get_block_height(b.prev_id) + 1;
+ // FIXME: consider moving away from block_extended_info at some point
+ block_extended_info bei = boost::value_initialized<block_extended_info>();
+ bei.bl = b;
+ bei.height = alt_chain.size() ? it_prev->second.height + 1 : m_db->get_block_height(b.prev_id) + 1;
- bool is_a_checkpoint;
- if(!m_checkpoints.check_block(bei.height, id, is_a_checkpoint))
- {
- LOG_ERROR("CHECKPOINT VALIDATION FAILED");
- bvc.m_verifivation_failed = true;
- return false;
- }
+ bool is_a_checkpoint;
+ if(!m_checkpoints.check_block(bei.height, id, is_a_checkpoint))
+ {
+ LOG_ERROR("CHECKPOINT VALIDATION FAILED");
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
- // Check the block's hash against the difficulty target for its alt chain
- m_is_in_checkpoint_zone = false;
- difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
- CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
- crypto::hash proof_of_work = null_hash;
- get_block_longhash(bei.bl, proof_of_work, bei.height);
- if(!check_hash(proof_of_work, current_diff))
- {
- LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
- bvc.m_verifivation_failed = true;
- return false;
- }
+ // Check the block's hash against the difficulty target for its alt chain
+ m_is_in_checkpoint_zone = false;
+ difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
+ CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
+ crypto::hash proof_of_work = null_hash;
+ get_block_longhash(bei.bl, proof_of_work, bei.height);
+ if(!check_hash(proof_of_work, current_diff))
+ {
+ LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
- if(!prevalidate_miner_transaction(b, bei.height))
- {
- LOG_PRINT_RED_L1("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect miner transaction.");
- bvc.m_verifivation_failed = true;
- return false;
+ if(!prevalidate_miner_transaction(b, bei.height))
+ {
+ LOG_PRINT_RED_L1("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect miner transaction.");
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
- }
+ // FIXME:
+ // this brings up an interesting point: consider allowing to get block
+ // difficulty both by height OR by hash, not just height.
+ difficulty_type main_chain_cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->height() - 1);
+ if (alt_chain.size())
+ {
+ bei.cumulative_difficulty = it_prev->second.cumulative_difficulty;
+ }
+ else
+ {
+ // passed-in block's previous block's cumulative difficulty, found on the main chain
+ bei.cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->get_block_height(b.prev_id));
+ }
+ bei.cumulative_difficulty += current_diff;
- // FIXME:
- // this brings up an interesting point: consider allowing to get block
- // difficulty both by height OR by hash, not just height.
- difficulty_type main_chain_cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->height() - 1);
- if (alt_chain.size())
- {
- bei.cumulative_difficulty = it_prev->second.cumulative_difficulty;
- }
- else
- {
- // passed-in block's previous block's cumulative difficulty, found on the main chain
- bei.cumulative_difficulty = m_db->get_block_cumulative_difficulty(m_db->get_block_height(b.prev_id));
- }
- bei.cumulative_difficulty += current_diff;
+ // add block to alternate blocks storage,
+ // as well as the current "alt chain" container
+ auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei));
+ CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist");
+ alt_chain.push_back(i_res.first);
- // add block to alternate blocks storage,
- // as well as the current "alt chain" container
- auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei));
- CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist");
- alt_chain.push_back(i_res.first);
+ // FIXME: is it even possible for a checkpoint to show up not on the main chain?
+ if(is_a_checkpoint)
+ {
+ //do reorganize!
+ LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << ", checkpoint is found in alternative chain on height " << bei.height, LOG_LEVEL_0);
- // FIXME: is it even possible for a checkpoint to show up not on the main chain?
- if(is_a_checkpoint)
- {
- //do reorganize!
- LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << ", checkpoint is found in alternative chain on height " << bei.height, LOG_LEVEL_0);
+ bool r = switch_to_alternative_blockchain(alt_chain, true);
- bool r = switch_to_alternative_blockchain(alt_chain, true);
+ bvc.m_added_to_main_chain = r;
+ bvc.m_verifivation_failed = !r;
- bvc.m_added_to_main_chain = r;
- bvc.m_verifivation_failed = !r;
+ return r;
+ }
+ else if(main_chain_cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain
+ {
+ //do reorganize!
+ LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << " with cum_difficulty " << m_db->get_block_cumulative_difficulty(m_db->height() - 1) << std::endl << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty, LOG_LEVEL_0);
- return r;
- }
- else if(main_chain_cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain
- {
- //do reorganize!
- LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << " with cum_difficulty " << m_db->get_block_cumulative_difficulty(m_db->height() - 1) << std::endl << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty, LOG_LEVEL_0);
-
- bool r = switch_to_alternative_blockchain(alt_chain, false);
- if (r)
- bvc.m_added_to_main_chain = true;
- else
- bvc.m_verifivation_failed = true;
- return r;
- }
- else
- {
- LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "difficulty:\t" << current_diff, LOG_LEVEL_0);
- return true;
- }
+ bool r = switch_to_alternative_blockchain(alt_chain, false);
+ if (r)
+ bvc.m_added_to_main_chain = true;
+ else
+ bvc.m_verifivation_failed = true;
+ return r;
}
else
{
- //block orphaned
- bvc.m_marked_as_orphaned = true;
- LOG_PRINT_RED_L1("Block recognized as orphaned and rejected, id = " << id);
+ LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "difficulty:\t" << current_diff, LOG_LEVEL_0);
+ return true;
}
+ }
+ else
+ {
+ //block orphaned
+ bvc.m_marked_as_orphaned = true;
+ LOG_PRINT_RED_L1("Block recognized as orphaned and rejected, id = " << id);
+ }
- return true;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list<block>& blocks, std::list<transaction>& txs) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- if(start_offset > m_db->height())
- return false;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ if(start_offset > m_db->height())
+ return false;
- if (!get_blocks(start_offset, count, blocks))
- {
- return false;
- }
+ if (!get_blocks(start_offset, count, blocks))
+ {
+ return false;
+ }
- for(const block& blk : blocks)
- {
- std::list<crypto::hash> missed_ids;
- get_transactions(blk.tx_hashes, txs, missed_ids);
- CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "has missed transactions in own block in main blockchain");
- }
+ for(const block& blk : blocks)
+ {
+ std::list<crypto::hash> missed_ids;
+ get_transactions(blk.tx_hashes, txs, missed_ids);
+ CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "has missed transactions in own block in main blockchain");
+ }
- return true;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list<block>& blocks) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- if(start_offset > m_db->height())
- return false;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ if(start_offset > m_db->height())
+ return false;
- for(size_t i = start_offset; i < start_offset + count && i < m_db->height();i++)
- {
- blocks.push_back(m_db->get_block_from_height(i));
- }
- return true;
+ for(size_t i = start_offset; i < start_offset + count && i < m_db->height();i++)
+ {
+ blocks.push_back(m_db->get_block_from_height(i));
+ }
+ return true;
}
//------------------------------------------------------------------
//TODO: This function *looks* like it won't need to be rewritten
@@ -1376,68 +1375,67 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list<block
// but it warrants some looking into later.
bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- rsp.current_blockchain_height = get_current_blockchain_height();
- std::list<block> blocks;
- get_blocks(arg.blocks, blocks, rsp.missed_ids);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ rsp.current_blockchain_height = get_current_blockchain_height();
+ std::list<block> blocks;
+ get_blocks(arg.blocks, blocks, rsp.missed_ids);
- BOOST_FOREACH(const auto& bl, blocks)
- {
- std::list<crypto::hash> missed_tx_id;
- std::list<transaction> txs;
- get_transactions(bl.tx_hashes, txs, rsp.missed_ids);
- CHECK_AND_ASSERT_MES(!missed_tx_id.size(), false, "Internal error: has missed missed_tx_id.size()=" << missed_tx_id.size()
- << std::endl << "for block id = " << get_block_hash(bl));
- rsp.blocks.push_back(block_complete_entry());
- block_complete_entry& e = rsp.blocks.back();
- //pack block
- e.block = t_serializable_object_to_blob(bl);
- //pack transactions
- BOOST_FOREACH(transaction& tx, txs)
- e.txs.push_back(t_serializable_object_to_blob(tx));
-
- }
- //get another transactions, if need
+ BOOST_FOREACH(const auto& bl, blocks)
+ {
+ std::list<crypto::hash> missed_tx_id;
std::list<transaction> txs;
- get_transactions(arg.txs, txs, rsp.missed_ids);
- //pack aside transactions
- BOOST_FOREACH(const auto& tx, txs)
+ get_transactions(bl.tx_hashes, txs, rsp.missed_ids);
+ CHECK_AND_ASSERT_MES(!missed_tx_id.size(), false, "Internal error: has missed missed_tx_id.size()=" << missed_tx_id.size()
+ << std::endl << "for block id = " << get_block_hash(bl));
+ rsp.blocks.push_back(block_complete_entry());
+ block_complete_entry& e = rsp.blocks.back();
+ //pack block
+ e.block = t_serializable_object_to_blob(bl);
+ //pack transactions
+ BOOST_FOREACH(transaction& tx, txs)
+ e.txs.push_back(t_serializable_object_to_blob(tx));
+ }
+ //get another transactions, if need
+ std::list<transaction> txs;
+ get_transactions(arg.txs, txs, rsp.missed_ids);
+ //pack aside transactions
+ BOOST_FOREACH(const auto& tx, txs)
rsp.txs.push_back(t_serializable_object_to_blob(tx));
- return true;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::get_alternative_blocks(std::list<block>& blocks) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- BOOST_FOREACH(const auto& alt_bl, m_alternative_chains)
- {
- blocks.push_back(alt_bl.second.bl);
- }
- return true;
+ BOOST_FOREACH(const auto& alt_bl, m_alternative_chains)
+ {
+ blocks.push_back(alt_bl.second.bl);
+ }
+ return true;
}
//------------------------------------------------------------------
size_t Blockchain::get_alternative_blocks_count() const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- return m_alternative_chains.size();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ return m_alternative_chains.size();
}
//------------------------------------------------------------------
// This function adds the output specified by <amount, i> to the result_outs container
// unlocked and other such checks should be done by here.
void Blockchain::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry());
- oen.global_amount_index = i;
- output_data_t data = m_db->get_output_key(amount, i);
- oen.out_key = data.pubkey;
+ COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry());
+ oen.global_amount_index = i;
+ output_data_t data = m_db->get_output_key(amount, i);
+ oen.out_key = data.pubkey;
}
//------------------------------------------------------------------
// This function takes an RPC request for mixins and creates an RPC response
@@ -1446,90 +1444,90 @@ void Blockchain::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_A
// in some cases
bool Blockchain::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+
+ // for each amount that we need to get mixins for, get <n> random outputs
+ // from BlockchainDB where <n> is req.outs_count (number of mixins).
+ for (uint64_t amount : req.amounts)
+ {
+ auto num_outs = m_db->get_num_outputs(amount);
+ // ensure we don't include outputs that aren't yet eligible to be used
+ // outpouts are sorted by height
+ while (num_outs > 0)
+ {
+ const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1);
+ const uint64_t height = m_db->get_tx_block_height(toi.first);
+ if (height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE <= m_db->height())
+ break;
+ --num_outs;
+ }
+
+ // create outs_for_amount struct and populate amount field
+ COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs = *res.outs.insert(res.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount());
+ result_outs.amount = amount;
+
+ std::unordered_set<uint64_t> seen_indices;
- // for each amount that we need to get mixins for, get <n> random outputs
- // from BlockchainDB where <n> is req.outs_count (number of mixins).
- for (uint64_t amount : req.amounts)
+ // if there aren't enough outputs to mix with (or just enough),
+ // use all of them. Eventually this should become impossible.
+ if (num_outs <= req.outs_count)
{
- auto num_outs = m_db->get_num_outputs(amount);
- // ensure we don't include outputs that aren't yet eligible to be used
- // outpouts are sorted by height
- while (num_outs > 0)
+ for (uint64_t i = 0; i < num_outs; i++)
+ {
+ // get tx_hash, tx_out_index from DB
+ tx_out_index toi = m_db->get_output_tx_and_index(amount, i);
+
+ // if tx is unlocked, add output to result_outs
+ if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
{
- const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1);
- const uint64_t height = m_db->get_tx_block_height(toi.first);
- if (height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE <= m_db->height())
- break;
- --num_outs;
+ add_out_to_get_random_outs(result_outs, amount, i);
+ }
+
+ }
+ }
+ else
+ {
+ // while we still need more mixins
+ while (result_outs.outs.size() < req.outs_count)
+ {
+ // if we've gone through every possible output, we've gotten all we can
+ if (seen_indices.size() == num_outs)
+ {
+ break;
}
- // create outs_for_amount struct and populate amount field
- COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs = *res.outs.insert(res.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount());
- result_outs.amount = amount;
+ // get a random output index from the DB. If we've already seen it,
+ // return to the top of the loop and try again, otherwise add it to the
+ // list of output indices we've seen.
- std::unordered_set<uint64_t> seen_indices;
+ // triangular distribution over [a,b) with a=0, mode c=b=up_index_limit
+ uint64_t r = crypto::rand<uint64_t>() % ((uint64_t)1 << 53);
+ double frac = std::sqrt((double)r / ((uint64_t)1 << 53));
+ uint64_t i = (uint64_t)(frac*num_outs);
+ // just in case rounding up to 1 occurs after sqrt
+ if (i == num_outs)
+ --i;
- // if there aren't enough outputs to mix with (or just enough),
- // use all of them. Eventually this should become impossible.
- if (num_outs <= req.outs_count)
+ if (seen_indices.count(i))
{
- for (uint64_t i = 0; i < num_outs; i++)
- {
- // get tx_hash, tx_out_index from DB
- tx_out_index toi = m_db->get_output_tx_and_index(amount, i);
+ continue;
+ }
+ seen_indices.emplace(i);
- // if tx is unlocked, add output to result_outs
- if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
- {
- add_out_to_get_random_outs(result_outs, amount, i);
- }
+ // get tx_hash, tx_out_index from DB
+ tx_out_index toi = m_db->get_output_tx_and_index(amount, i);
- }
- }
- else
+ // if the output's transaction is unlocked, add the output's index to
+ // our list.
+ if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
{
- // while we still need more mixins
- while (result_outs.outs.size() < req.outs_count)
- {
- // if we've gone through every possible output, we've gotten all we can
- if (seen_indices.size() == num_outs)
- {
- break;
- }
-
- // get a random output index from the DB. If we've already seen it,
- // return to the top of the loop and try again, otherwise add it to the
- // list of output indices we've seen.
-
- // triangular distribution over [a,b) with a=0, mode c=b=up_index_limit
- uint64_t r = crypto::rand<uint64_t>() % ((uint64_t)1 << 53);
- double frac = std::sqrt((double)r / ((uint64_t)1 << 53));
- uint64_t i = (uint64_t)(frac*num_outs);
- // just in case rounding up to 1 occurs after sqrt
- if (i == num_outs)
- --i;
-
- if (seen_indices.count(i))
- {
- continue;
- }
- seen_indices.emplace(i);
-
- // get tx_hash, tx_out_index from DB
- tx_out_index toi = m_db->get_output_tx_and_index(amount, i);
-
- // if the output's transaction is unlocked, add the output's index to
- // our list.
- if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
- {
- add_out_to_get_random_outs(result_outs, amount, i);
- }
- }
+ add_out_to_get_random_outs(result_outs, amount, i);
}
+ }
}
- return true;
+ }
+ return true;
}
//------------------------------------------------------------------
// This function takes a list of block hashes from another node
@@ -1537,175 +1535,175 @@ bool Blockchain::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUT
// This is used to see what to send another node that needs to sync.
bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, uint64_t& starter_offset) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- // make sure the request includes at least the genesis block, otherwise
- // how can we expect to sync from the client that the block list came from?
- if(!qblock_ids.size() /*|| !req.m_total_height*/)
+ // make sure the request includes at least the genesis block, otherwise
+ // how can we expect to sync from the client that the block list came from?
+ if(!qblock_ids.size() /*|| !req.m_total_height*/)
+ {
+ LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << /*", m_height=" << req.m_total_height <<*/ ", dropping connection");
+ return false;
+ }
+
+ // 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)
+ {
+ LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block missmatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
+ return false;
+ }
+
+ // Find the first block the foreign chain has that we also have.
+ // Assume qblock_ids is in reverse-chronological order.
+ auto bl_it = qblock_ids.begin();
+ uint64_t split_height = 0;
+ for(; bl_it != qblock_ids.end(); bl_it++)
+ {
+ try
{
- LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << /*", m_height=" << req.m_total_height <<*/ ", dropping connection");
- return false;
+ split_height = m_db->get_block_height(*bl_it);
+ break;
}
-
- // 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)
+ catch (const BLOCK_DNE& e)
{
- LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block missmatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
- return false;
+ continue;
}
-
- // Find the first block the foreign chain has that we also have.
- // Assume qblock_ids is in reverse-chronological order.
- auto bl_it = qblock_ids.begin();
- uint64_t split_height = 0;
- for(; bl_it != qblock_ids.end(); bl_it++)
+ catch (const std::exception& e)
{
- try
- {
- split_height = m_db->get_block_height(*bl_it);
- break;
- }
- catch (const BLOCK_DNE& e)
- {
- continue;
- }
- catch (const std::exception& e)
- {
- LOG_PRINT_L1("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
- return false;
- }
+ LOG_PRINT_L1("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
+ return false;
}
+ }
- // this should be impossible, as we checked that we share the genesis block,
- // but just in case...
- if(bl_it == qblock_ids.end())
- {
- LOG_PRINT_L1("Internal error handling connection, can't find split point");
- return false;
- }
+ // this should be impossible, as we checked that we share the genesis block,
+ // but just in case...
+ if(bl_it == qblock_ids.end())
+ {
+ LOG_PRINT_L1("Internal error handling connection, can't find split point");
+ return false;
+ }
- // if split_height remains 0, we didn't have any but the genesis block in common
- // which is only fine if the blocks just have the genesis block
- if(split_height == 0 && qblock_ids.size() > 1)
- {
- LOG_ERROR("Ours and foreign blockchain have only genesis block in common... o.O");
- return false;
- }
+ // if split_height remains 0, we didn't have any but the genesis block in common
+ // which is only fine if the blocks just have the genesis block
+ if(split_height == 0 && qblock_ids.size() > 1)
+ {
+ LOG_ERROR("Ours and foreign blockchain have only genesis block in common... o.O");
+ return false;
+ }
- //we start to put block ids INCLUDING last known id, just to make other side be sure
- starter_offset = split_height;
- return true;
+ //we start to put block ids INCLUDING last known id, just to make other side be sure
+ starter_offset = split_height;
+ return true;
}
//------------------------------------------------------------------
uint64_t Blockchain::block_difficulty(uint64_t i) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- try
- {
- return m_db->get_block_difficulty(i);
- }
- catch (const BLOCK_DNE& e)
- {
- LOG_PRINT_L0("Attempted to get block difficulty for height above blockchain height");
- }
- return 0;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ try
+ {
+ return m_db->get_block_difficulty(i);
+ }
+ catch (const BLOCK_DNE& e)
+ {
+ LOG_PRINT_L0("Attempted to get block difficulty for height above blockchain height");
+ }
+ return 0;
}
//------------------------------------------------------------------
template<class t_ids_container, class t_blocks_container, class t_missed_container>
bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- for (const auto& block_hash : block_ids)
+ for (const auto& block_hash : block_ids)
+ {
+ try
{
- try
- {
- blocks.push_back(m_db->get_block(block_hash));
- }
- catch (const BLOCK_DNE& e)
- {
- missed_bs.push_back(block_hash);
- }
- catch (const std::exception& e)
- {
- return false;
- }
+ blocks.push_back(m_db->get_block(block_hash));
}
- return true;
+ catch (const BLOCK_DNE& e)
+ {
+ missed_bs.push_back(block_hash);
+ }
+ catch (const std::exception& e)
+ {
+ return false;
+ }
+ }
+ return true;
}
//------------------------------------------------------------------
template<class t_ids_container, class t_tx_container, class t_missed_container>
bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- for (const auto& tx_hash : txs_ids)
+ for (const auto& tx_hash : txs_ids)
+ {
+ try
{
- try
- {
- txs.push_back(m_db->get_tx(tx_hash));
- }
- catch (const TX_DNE& e)
- {
- missed_txs.push_back(tx_hash);
- }
- //FIXME: is this the correct way to handle this?
- catch (const std::exception& e)
- {
- return false;
- }
+ txs.push_back(m_db->get_tx(tx_hash));
}
- return true;
+ catch (const TX_DNE& e)
+ {
+ missed_txs.push_back(tx_hash);
+ }
+ //FIXME: is this the correct way to handle this?
+ catch (const std::exception& e)
+ {
+ return false;
+ }
+ }
+ return true;
}
//------------------------------------------------------------------
void Blockchain::print_blockchain(uint64_t start_index, uint64_t end_index) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- std::stringstream ss;
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- auto h = m_db->height();
- if(start_index > h)
- {
- LOG_PRINT_L1("Wrong starter index set: " << start_index << ", expected max index " << h);
- return;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ std::stringstream ss;
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ auto h = m_db->height();
+ if(start_index > h)
+ {
+ LOG_PRINT_L1("Wrong starter index set: " << start_index << ", expected max index " << h);
+ return;
+ }
- for(size_t i = start_index; i <= h && i != end_index; i++)
- {
- ss << "height " << i << ", timestamp " << m_db->get_block_timestamp(i) << ", cumul_dif " << m_db->get_block_cumulative_difficulty(i) << ", size " << m_db->get_block_size(i) << "\nid\t\t" << m_db->get_block_hash_from_height(i) << "\ndifficulty\t\t" << m_db->get_block_difficulty(i) << ", nonce " << m_db->get_block_from_height(i).nonce << ", tx_count " << m_db->get_block_from_height(i).tx_hashes.size() << std::endl;
- }
- LOG_PRINT_L1("Current blockchain:" << std::endl << ss.str());
- LOG_PRINT_L0("Blockchain printed with log level 1");
+ for(size_t i = start_index; i <= h && i != end_index; i++)
+ {
+ ss << "height " << i << ", timestamp " << m_db->get_block_timestamp(i) << ", cumul_dif " << m_db->get_block_cumulative_difficulty(i) << ", size " << m_db->get_block_size(i) << "\nid\t\t" << m_db->get_block_hash_from_height(i) << "\ndifficulty\t\t" << m_db->get_block_difficulty(i) << ", nonce " << m_db->get_block_from_height(i).nonce << ", tx_count " << m_db->get_block_from_height(i).tx_hashes.size() << std::endl;
+ }
+ LOG_PRINT_L1("Current blockchain:" << std::endl << ss.str());
+ LOG_PRINT_L0("Blockchain printed with log level 1");
}
//------------------------------------------------------------------
void Blockchain::print_blockchain_index() const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- std::stringstream ss;
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- auto height = m_db->height();
- if (height != 0)
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ std::stringstream ss;
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ auto height = m_db->height();
+ if (height != 0)
+ {
+ for(uint64_t i = 0; i <= height; i++)
{
- for(uint64_t i = 0; i <= height; i++)
- {
- ss << "height: " << i << ", hash: " << m_db->get_block_hash_from_height(i);
- }
+ ss << "height: " << i << ", hash: " << m_db->get_block_hash_from_height(i);
}
+ }
- LOG_PRINT_L0("Current blockchain index:" << std::endl << ss.str());
+ LOG_PRINT_L0("Current blockchain index:" << std::endl << ss.str());
}
//------------------------------------------------------------------
//TODO: remove this function and references to it
void Blockchain::print_blockchain_outs(const std::string& file) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- return;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ return;
}
//------------------------------------------------------------------
// Find the split point between us and foreign blockchain and return
@@ -1713,22 +1711,22 @@ void Blockchain::print_blockchain_outs(const std::string& file) const
// BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes.
bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- // if we can't find the split point, return false
- if(!find_blockchain_supplement(qblock_ids, resp.start_height))
- {
- return false;
- }
+ // if we can't find the split point, return false
+ if(!find_blockchain_supplement(qblock_ids, resp.start_height))
+ {
+ return false;
+ }
- resp.total_height = get_current_blockchain_height();
- size_t count = 0;
- for(size_t i = resp.start_height; i < resp.total_height && count < BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT; i++, count++)
- {
- resp.m_block_ids.push_back(m_db->get_block_hash_from_height(i));
- }
- return true;
+ resp.total_height = get_current_blockchain_height();
+ size_t count = 0;
+ for(size_t i = resp.start_height; i < resp.total_height && count < BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT; i++, count++)
+ {
+ resp.m_block_ids.push_back(m_db->get_block_hash_from_height(i));
+ }
+ return true;
}
//------------------------------------------------------------------
//FIXME: change argument to std::vector, low priority
@@ -1737,82 +1735,82 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
// blocks by reference.
bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- // if a specific start height has been requested
- if(req_start_block > 0)
+ // if a specific start height has been requested
+ if(req_start_block > 0)
+ {
+ // if requested height is higher than our chain, return false -- we can't help
+ if (req_start_block >= m_db->height())
{
- // if requested height is higher than our chain, return false -- we can't help
- if (req_start_block >= m_db->height())
- {
- return false;
- }
- start_height = req_start_block;
+ return false;
}
- else
+ start_height = req_start_block;
+ }
+ else
+ {
+ if(!find_blockchain_supplement(qblock_ids, start_height))
{
- if(!find_blockchain_supplement(qblock_ids, start_height))
- {
- return false;
- }
+ return false;
}
+ }
- total_height = get_current_blockchain_height();
- size_t count = 0;
- for(size_t i = start_height; i < total_height && count < max_count; i++, count++)
- {
- blocks.resize(blocks.size()+1);
- blocks.back().first = m_db->get_block_from_height(i);
- std::list<crypto::hash> mis;
- get_transactions(blocks.back().first.tx_hashes, blocks.back().second, mis);
- CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
- }
- return true;
+ total_height = get_current_blockchain_height();
+ size_t count = 0;
+ for(size_t i = start_height; i < total_height && count < max_count; i++, count++)
+ {
+ blocks.resize(blocks.size()+1);
+ blocks.back().first = m_db->get_block_from_height(i);
+ std::list<crypto::hash> mis;
+ get_transactions(blocks.back().first.tx_hashes, blocks.back().second, mis);
+ CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
+ }
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::add_block_as_invalid(const block& bl, const crypto::hash& h)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- block_extended_info bei = AUTO_VAL_INIT(bei);
- bei.bl = bl;
- return add_block_as_invalid(bei, h);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ block_extended_info bei = AUTO_VAL_INIT(bei);
+ bei.bl = bl;
+ return add_block_as_invalid(bei, h);
}
//------------------------------------------------------------------
bool Blockchain::add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- auto i_res = m_invalid_blocks.insert(std::map<crypto::hash, block_extended_info>::value_type(h, bei));
- CHECK_AND_ASSERT_MES(i_res.second, false, "at insertion invalid by tx returned status existed");
- LOG_PRINT_L1("BLOCK ADDED AS INVALID: " << h << std::endl << ", prev_id=" << bei.bl.prev_id << ", m_invalid_blocks count=" << m_invalid_blocks.size());
- return true;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ auto i_res = m_invalid_blocks.insert(std::map<crypto::hash, block_extended_info>::value_type(h, bei));
+ CHECK_AND_ASSERT_MES(i_res.second, false, "at insertion invalid by tx returned status existed");
+ LOG_PRINT_L1("BLOCK ADDED AS INVALID: " << h << std::endl << ", prev_id=" << bei.bl.prev_id << ", m_invalid_blocks count=" << m_invalid_blocks.size());
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::have_block(const crypto::hash& id) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- if(m_db->block_exists(id))
- {
- LOG_PRINT_L3("block exists in main chain");
- return true;
- }
+ if(m_db->block_exists(id))
+ {
+ LOG_PRINT_L3("block exists in main chain");
+ return true;
+ }
- if(m_alternative_chains.count(id))
- {
- LOG_PRINT_L3("block found in m_alternative_chains");
- return true;
- }
+ if(m_alternative_chains.count(id))
+ {
+ LOG_PRINT_L3("block found in m_alternative_chains");
+ return true;
+ }
- if(m_invalid_blocks.count(id))
- {
- LOG_PRINT_L3("block found in m_invalid_blocks");
- return true;
- }
+ if(m_invalid_blocks.count(id))
+ {
+ LOG_PRINT_L3("block found in m_invalid_blocks");
+ return true;
+ }
- return false;
+ return false;
}
//------------------------------------------------------------------
bool Blockchain::handle_block_to_main_chain(const block& bl, block_verification_context& bvc)
@@ -1824,9 +1822,9 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, block_verification_
//------------------------------------------------------------------
size_t Blockchain::get_total_transactions() const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- return m_db->get_tx_count();
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ return m_db->get_tx_count();
}
//------------------------------------------------------------------
// This function checks each input in the transaction <tx> to make sure it
@@ -1837,79 +1835,79 @@ size_t Blockchain::get_total_transactions() const
// remove them later if the block fails validation.
bool Blockchain::check_for_double_spend(const transaction& tx, key_images_container& keys_this_block) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- struct add_transaction_input_visitor: public boost::static_visitor<bool>
- {
- key_images_container& m_spent_keys;
- BlockchainDB* m_db;
- add_transaction_input_visitor(key_images_container& spent_keys, BlockchainDB* db) :
- m_spent_keys(spent_keys), m_db(db)
- {
- }
- bool operator()(const txin_to_key& in) const
- {
- const crypto::key_image& ki = in.k_image;
-
- // attempt to insert the newly-spent key into the container of
- // keys spent this block. If this fails, the key was spent already
- // in this block, return false to flag that a double spend was detected.
- //
- // if the insert into the block-wide spent keys container succeeds,
- // check the blockchain-wide spent keys container and make sure the
- // key wasn't used in another block already.
- auto r = m_spent_keys.insert(ki);
- if(!r.second || m_db->has_key_image(ki))
- {
- //double spend detected
- return false;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ struct add_transaction_input_visitor: public boost::static_visitor<bool>
+ {
+ key_images_container& m_spent_keys;
+ BlockchainDB* m_db;
+ add_transaction_input_visitor(key_images_container& spent_keys, BlockchainDB* db) :
+ m_spent_keys(spent_keys), m_db(db)
+ {
+ }
+ bool operator()(const txin_to_key& in) const
+ {
+ const crypto::key_image& ki = in.k_image;
+
+ // attempt to insert the newly-spent key into the container of
+ // keys spent this block. If this fails, the key was spent already
+ // in this block, return false to flag that a double spend was detected.
+ //
+ // if the insert into the block-wide spent keys container succeeds,
+ // check the blockchain-wide spent keys container and make sure the
+ // key wasn't used in another block already.
+ auto r = m_spent_keys.insert(ki);
+ if(!r.second || m_db->has_key_image(ki))
+ {
+ //double spend detected
+ return false;
+ }
- // if no double-spend detected, return true
- return true;
- }
+ // if no double-spend detected, return true
+ return true;
+ }
- bool operator()(const txin_gen& tx) const
- {
- return true;
- }
- bool operator()(const txin_to_script& tx) const
- {
- return false;
- }
- bool operator()(const txin_to_scripthash& tx) const
- {
- return false;
- }
- };
+ bool operator()(const txin_gen& tx) const
+ {
+ return true;
+ }
+ bool operator()(const txin_to_script& tx) const
+ {
+ return false;
+ }
+ bool operator()(const txin_to_scripthash& tx) const
+ {
+ return false;
+ }
+ };
- for (const txin_v& in : tx.vin)
+ for (const txin_v& in : tx.vin)
+ {
+ if(!boost::apply_visitor(add_transaction_input_visitor(keys_this_block, m_db), in))
{
- if(!boost::apply_visitor(add_transaction_input_visitor(keys_this_block, m_db), in))
- {
- LOG_ERROR("Double spend detected!");
- return false;
- }
+ LOG_ERROR("Double spend detected!");
+ return false;
}
+ }
- return true;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- if (!m_db->tx_exists(tx_id))
- {
- LOG_PRINT_RED_L1("warning: get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
- return false;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ if (!m_db->tx_exists(tx_id))
+ {
+ LOG_PRINT_RED_L1("warning: get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
+ return false;
+ }
- // get amount output indexes, currently referred to in parts as "output global indices", but they are actually specific to amounts
- indexs = m_db->get_tx_amount_output_indices(tx_id);
- CHECK_AND_ASSERT_MES(indexs.size(), false, "internal error: global indexes for transaction " << tx_id << " is empty");
+ // get amount output indexes, currently referred to in parts as "output global indices", but they are actually specific to amounts
+ indexs = m_db->get_tx_amount_output_indices(tx_id);
+ CHECK_AND_ASSERT_MES(indexs.size(), false, "internal error: global indexes for transaction " << tx_id << " is empty");
- return true;
+ return true;
}
//------------------------------------------------------------------
// This function overloads its sister function with
@@ -1917,71 +1915,71 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<u
// as a return-by-reference.
bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block_height, crypto::hash& max_used_block_id, bool kept_by_block)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
#if defined(PER_BLOCK_CHECKPOINT)
- // check if we're doing per-block checkpointing
- if (m_db->height() < m_blocks_hash_check.size() && kept_by_block)
- {
- TIME_MEASURE_START(a);
- m_blocks_txs_check.push_back(get_transaction_hash(tx));
- max_used_block_id = null_hash;
- max_used_block_height = 0;
- TIME_MEASURE_FINISH(a);
- if(m_show_time_stats)
- LOG_PRINT_L0("HASH: " << "-" << " VIN/VOUT: " << tx.vin.size() << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
- return true;
- }
-#endif
-
+ // check if we're doing per-block checkpointing
+ if (m_db->height() < m_blocks_hash_check.size() && kept_by_block)
+ {
TIME_MEASURE_START(a);
- bool res = check_tx_inputs(tx, &max_used_block_height);
+ m_blocks_txs_check.push_back(get_transaction_hash(tx));
+ max_used_block_id = null_hash;
+ max_used_block_height = 0;
TIME_MEASURE_FINISH(a);
- crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx);
if(m_show_time_stats)
- LOG_PRINT_L0("HASH: " << "+" << " VIN/VOUT: " << tx.vin.size() << "/" << tx.vout.size() << " H: " << max_used_block_height << " chcktx: " << a + m_fake_scan_time);
+ LOG_PRINT_L0("HASH: " << "-" << " VIN/VOUT: " << tx.vin.size() << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
+ return true;
+ }
+#endif
- if (!res)
- return false;
+ TIME_MEASURE_START(a);
+ bool res = check_tx_inputs(tx, &max_used_block_height);
+ TIME_MEASURE_FINISH(a);
+ crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx);
+ if(m_show_time_stats)
+ LOG_PRINT_L0("HASH: " << "+" << " VIN/VOUT: " << tx.vin.size() << "/" << tx.vout.size() << " H: " << max_used_block_height << " chcktx: " << a + m_fake_scan_time);
- // ND: Speedup:
- // 1. keep a list of verified transactions, when the Blockchain tries to check a tx again,
- // verify against list and skip if already verified to be correct.
- m_check_tx_inputs_table.emplace(tx_prefix_hash, std::make_pair(res, max_used_block_height));
+ if (!res)
+ return false;
- CHECK_AND_ASSERT_MES(max_used_block_height < m_db->height(), false, "internal error: max used block index=" << max_used_block_height << " is not less then blockchain size = " << m_db->height());
- max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height);
- return true;
+ // ND: Speedup:
+ // 1. keep a list of verified transactions, when the Blockchain tries to check a tx again,
+ // verify against list and skip if already verified to be correct.
+ m_check_tx_inputs_table.emplace(tx_prefix_hash, std::make_pair(res, max_used_block_height));
+
+ CHECK_AND_ASSERT_MES(max_used_block_height < m_db->height(), false, "internal error: max used block index=" << max_used_block_height << " is not less then blockchain size = " << m_db->height());
+ max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height);
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::check_tx_outputs(const transaction& tx)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- // from hard fork 2, we forbid dust and compound outputs
- if (m_hardfork->get_current_version() >= 2) {
- BOOST_FOREACH(auto &o, tx.vout) {
- if (!is_valid_decomposed_amount(o.amount)) {
- return false;
- }
+ // from hard fork 2, we forbid dust and compound outputs
+ if (m_hardfork->get_current_version() >= 2) {
+ BOOST_FOREACH(auto &o, tx.vout) {
+ if (!is_valid_decomposed_amount(o.amount)) {
+ return false;
}
}
+ }
- return true;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- BOOST_FOREACH(const txin_v& in, tx.vin)
- {
- CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, in_to_key, true);
- if(have_tx_keyimg_as_spent(in_to_key.k_image))
- return true;
- }
- return false;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ BOOST_FOREACH(const txin_v& in, tx.vin)
+ {
+ CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, in_to_key, true);
+ if(have_tx_keyimg_as_spent(in_to_key.k_image))
+ return true;
+ }
+ return false;
}
//------------------------------------------------------------------
// This function validates transaction inputs and their keys. Previously
@@ -1989,87 +1987,87 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
// own function.
bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_block_height)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- size_t sig_index = 0;
- if(pmax_used_block_height)
- *pmax_used_block_height = 0;
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ size_t sig_index = 0;
+ if(pmax_used_block_height)
+ *pmax_used_block_height = 0;
- crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx);
+ crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx);
- auto its = m_check_tx_inputs_table.find(tx_prefix_hash);
- if (its != m_check_tx_inputs_table.end())
+ auto its = m_check_tx_inputs_table.find(tx_prefix_hash);
+ if (its != m_check_tx_inputs_table.end())
+ {
+ if (!its->second.first)
+ return false;
+ if (pmax_used_block_height)
+ *pmax_used_block_height = its->second.second;
+ return true;
+ }
+
+ // from hard fork 2, we require mixin at least 2 unless one output cannot mix with 2 others
+ // if one output cannot mix with 2 others, we accept at most 1 output that can mix
+ if (m_hardfork->get_current_version() >= 2)
+ {
+ size_t n_unmixable = 0, n_mixable = 0;
+ size_t mixin = std::numeric_limits<size_t>::max();
+ for (const auto& txin : tx.vin)
{
- if (!its->second.first)
- return false;
- if (pmax_used_block_height)
- *pmax_used_block_height = its->second.second;
- return true;
+ // non txin_to_key inputs will be rejected below
+ if (txin.type() == typeid(txin_to_key))
+ {
+ const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
+ uint64_t n_outputs = m_db->get_num_outputs(in_to_key.amount);
+ // n_outputs includes the output we're considering
+ if (n_outputs <= 2)
+ ++n_unmixable;
+ else
+ ++n_mixable;
+ if (in_to_key.key_offsets.size() - 1 < mixin)
+ mixin = in_to_key.key_offsets.size() - 1;
+ }
}
-
- // from hard fork 2, we require mixin at least 2 unless one output cannot mix with 2 others
- // if one output cannot mix with 2 others, we accept at most 1 output that can mix
- if (m_hardfork->get_current_version() >= 2)
+ if (mixin < 2)
{
- size_t n_unmixable = 0, n_mixable = 0;
- size_t mixin = std::numeric_limits<size_t>::max();
- for (const auto& txin : tx.vin)
- {
- // non txin_to_key inputs will be rejected below
- if (txin.type() == typeid(txin_to_key))
- {
- const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
- uint64_t n_outputs = m_db->get_num_outputs(in_to_key.amount);
- // n_outputs includes the output we're considering
- if (n_outputs <= 2)
- ++n_unmixable;
- else
- ++n_mixable;
- if (in_to_key.key_offsets.size() - 1 < mixin)
- mixin = in_to_key.key_offsets.size() - 1;
- }
- }
- if (mixin < 2)
- {
- if (n_unmixable == 0)
- {
- LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and no unmixable inputs");
- return false;
- }
- if (n_mixable > 1)
- {
- LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and more than one mixable input with unmixable inputs");
- return false;
- }
- }
+ if (n_unmixable == 0)
+ {
+ LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and no unmixable inputs");
+ return false;
+ }
+ if (n_mixable > 1)
+ {
+ LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and more than one mixable input with unmixable inputs");
+ return false;
+ }
}
+ }
- auto it = m_check_txin_table.find(tx_prefix_hash);
- if(it == m_check_txin_table.end())
- {
- m_check_txin_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, bool>());
- it = m_check_txin_table.find(tx_prefix_hash);
- assert(it != m_check_txin_table.end());
- }
+ auto it = m_check_txin_table.find(tx_prefix_hash);
+ if(it == m_check_txin_table.end())
+ {
+ m_check_txin_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, bool>());
+ it = m_check_txin_table.find(tx_prefix_hash);
+ assert(it != m_check_txin_table.end());
+ }
- uint64_t t_t1 = 0;
- std::vector<std::vector<crypto::public_key>> pubkeys(tx.vin.size());
- std::vector < uint64_t > results;
- results.resize(tx.vin.size(), 0);
+ uint64_t t_t1 = 0;
+ std::vector<std::vector<crypto::public_key>> pubkeys(tx.vin.size());
+ std::vector < uint64_t > results;
+ results.resize(tx.vin.size(), 0);
- int threads = std::thread::hardware_concurrency();
+ int threads = std::thread::hardware_concurrency();
- boost::asio::io_service ioservice;
- boost::thread_group threadpool;
+ boost::asio::io_service ioservice;
+ boost::thread_group threadpool;
+
+ std::auto_ptr < boost::asio::io_service::work > work(new boost::asio::io_service::work(ioservice));
+ if(threads > 1)
+ {
+ for (int i = 0; i < threads; i++)
+ {
+ threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
+ }
+ }
- std::auto_ptr < boost::asio::io_service::work > work(new boost::asio::io_service::work(ioservice));
- if(threads > 1)
- {
- for (int i = 0; i < threads; i++)
- {
- threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
- }
- }
-
#define KILL_IOSERVICE() \
if(threads > 1) \
{ \
@@ -2078,119 +2076,119 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_bloc
ioservice.stop(); \
} \
- for (const auto& txin : tx.vin)
- {
- // make sure output being spent is of type txin_to_key, rather than
- // e.g. txin_gen, which is only used for miner transactions
- CHECK_AND_ASSERT_MES(txin.type() == typeid(txin_to_key), false, "wrong type id in tx input at Blockchain::check_tx_inputs");
- const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
+ for (const auto& txin : tx.vin)
+ {
+ // make sure output being spent is of type txin_to_key, rather than
+ // e.g. txin_gen, which is only used for miner transactions
+ CHECK_AND_ASSERT_MES(txin.type() == typeid(txin_to_key), false, "wrong type id in tx input at Blockchain::check_tx_inputs");
+ const txin_to_key& in_to_key = boost::get<txin_to_key>(txin);
- // make sure tx output has key offset(s) (is signed to be used)
- CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "empty in_to_key.key_offsets in transaction with id " << get_transaction_hash(tx));
+ // make sure tx output has key offset(s) (is signed to be used)
+ CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "empty in_to_key.key_offsets in transaction with id " << get_transaction_hash(tx));
- // basically, make sure number of inputs == number of signatures
- CHECK_AND_ASSERT_MES(sig_index < tx.signatures.size(), false, "wrong transaction: not signature entry for input with index= " << sig_index);
+ // basically, make sure number of inputs == number of signatures
+ CHECK_AND_ASSERT_MES(sig_index < tx.signatures.size(), false, "wrong transaction: not signature entry for input with index= " << sig_index);
#if defined(CACHE_VIN_RESULTS)
- auto itk = it->second.find(in_to_key.k_image);
- if(itk != it->second.end())
- {
- 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);
- return false;
- }
-
- // txin has been verified already, skip
- sig_index++;
- continue;
- }
+ auto itk = it->second.find(in_to_key.k_image);
+ if(itk != it->second.end())
+ {
+ 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);
+ return false;
+ }
+
+ // txin has been verified already, skip
+ sig_index++;
+ continue;
+ }
#endif
- // make sure that output being spent matches up correctly with the
- // signature spending it.
- TIME_MEASURE_START(aa);
- if (!check_tx_input(in_to_key, tx_prefix_hash, tx.signatures[sig_index], pubkeys[sig_index], pmax_used_block_height))
- {
- it->second[in_to_key.k_image] = false;
- LOG_PRINT_L1("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
- if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
- {
- LOG_PRINT_L1(" *pmax_used_block_height: " << *pmax_used_block_height);
- }
+ // make sure that output being spent matches up correctly with the
+ // signature spending it.
+ TIME_MEASURE_START(aa);
+ if (!check_tx_input(in_to_key, tx_prefix_hash, tx.signatures[sig_index], pubkeys[sig_index], pmax_used_block_height))
+ {
+ it->second[in_to_key.k_image] = false;
+ LOG_PRINT_L1("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
+ if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
+ {
+ LOG_PRINT_L1(" *pmax_used_block_height: " << *pmax_used_block_height);
+ }
- KILL_IOSERVICE();
- return false;
- }
+ KILL_IOSERVICE();
+ return false;
+ }
- if (threads > 1)
+ if (threads > 1)
+ {
+ // ND: Speedup
+ // 1. Thread ring signature verification if possible.
+ ioservice.dispatch(boost::bind(&Blockchain::check_ring_signature, this, std::cref(tx_prefix_hash), std::cref(in_to_key.k_image), std::cref(pubkeys[sig_index]), std::cref(tx.signatures[sig_index]), std::ref(results[sig_index])));
+ }
+ else
+ {
+ check_ring_signature(tx_prefix_hash, in_to_key.k_image, pubkeys[sig_index], tx.signatures[sig_index], results[sig_index]);
+ if (!results[sig_index])
+ {
+ it->second[in_to_key.k_image] = false;
+ LOG_PRINT_L1("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
+
+ if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
{
- // ND: Speedup
- // 1. Thread ring signature verification if possible.
- ioservice.dispatch(boost::bind(&Blockchain::check_ring_signature, this, std::cref(tx_prefix_hash), std::cref(in_to_key.k_image), std::cref(pubkeys[sig_index]), std::cref(tx.signatures[sig_index]), std::ref(results[sig_index])));
+ LOG_PRINT_L1("*pmax_used_block_height: " << *pmax_used_block_height);
}
- else
- {
- check_ring_signature(tx_prefix_hash, in_to_key.k_image, pubkeys[sig_index], tx.signatures[sig_index], results[sig_index]);
- if (!results[sig_index])
- {
- it->second[in_to_key.k_image] = false;
- LOG_PRINT_L1("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
- if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
- {
- LOG_PRINT_L1("*pmax_used_block_height: " << *pmax_used_block_height);
- }
+ KILL_IOSERVICE();
+ return false;
+ }
+ it->second[in_to_key.k_image] = true;
+ }
- KILL_IOSERVICE();
- return false;
- }
- it->second[in_to_key.k_image] = true;
- }
+ sig_index++;
+ }
- sig_index++;
- }
+ KILL_IOSERVICE();
- KILL_IOSERVICE();
+ if (threads > 1)
+ {
+ // save results to table, passed or otherwise
+ bool failed = false;
+ for (size_t i = 0; i < tx.vin.size(); i++)
+ {
+ const txin_to_key& in_to_key = boost::get<txin_to_key>(tx.vin[i]);
+ it->second[in_to_key.k_image] = results[i];
+ if(!failed && !results[i])
+ failed = true;
+ }
- if (threads > 1)
+ if (failed)
{
- // save results to table, passed or otherwise
- bool failed = false;
- for (size_t i = 0; i < tx.vin.size(); i++)
- {
- const txin_to_key& in_to_key = boost::get<txin_to_key>(tx.vin[i]);
- it->second[in_to_key.k_image] = results[i];
- if(!failed && !results[i])
- failed = true;
- }
-
- if (failed)
- {
- LOG_PRINT_L1("Failed to check ring signatures!, t_loop: " << t_t1);
- return false;
- }
+ LOG_PRINT_L1("Failed to check ring signatures!, t_loop: " << t_t1);
+ return false;
}
- LOG_PRINT_L1("t_loop: " << t_t1);
- return true;
+ }
+ LOG_PRINT_L1("t_loop: " << t_t1);
+ return true;
}
//------------------------------------------------------------------
void Blockchain::check_ring_signature(const crypto::hash &tx_prefix_hash, const crypto::key_image &key_image, const std::vector<crypto::public_key> &pubkeys, const std::vector<crypto::signature>& sig, uint64_t &result)
{
- if (m_is_in_checkpoint_zone)
- {
- result = true;
- return;
- }
+ if (m_is_in_checkpoint_zone)
+ {
+ result = true;
+ return;
+ }
- std::vector<const crypto::public_key *> p_output_keys;
- for (auto &key : pubkeys)
- {
- p_output_keys.push_back(&key);
- }
+ std::vector<const crypto::public_key *> p_output_keys;
+ for (auto &key : pubkeys)
+ {
+ p_output_keys.push_back(&key);
+ }
- result = crypto::check_ring_signature(tx_prefix_hash, key_image, p_output_keys, sig.data()) ? 1 : 0;
+ result = crypto::check_ring_signature(tx_prefix_hash, key_image, p_output_keys, sig.data()) ? 1 : 0;
}
//------------------------------------------------------------------
@@ -2198,26 +2196,26 @@ void Blockchain::check_ring_signature(const crypto::hash &tx_prefix_hash, const
// a block index or a unix time.
bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
- {
- // ND: Instead of calling get_current_blockchain_height(), call m_db->height()
- // directly as get_current_blockchain_height() locks the recursive mutex.
- if(m_db->height() + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_time)
- return true;
- else
- return false;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
+ {
+ // ND: Instead of calling get_current_blockchain_height(), call m_db->height()
+ // directly as get_current_blockchain_height() locks the recursive mutex.
+ if(m_db->height() + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_time)
+ return true;
else
- {
- //interpret as time
- uint64_t current_time = static_cast<uint64_t>(time(NULL));
- if(current_time + (get_current_hard_fork_version() < 2 ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS) >= unlock_time)
- return true;
- else
- return false;
- }
- return false;
+ return false;
+ }
+ else
+ {
+ //interpret as time
+ uint64_t current_time = static_cast<uint64_t>(time(NULL));
+ if(current_time + (get_current_hard_fork_version() < 2 ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS) >= unlock_time)
+ return true;
+ else
+ return false;
+ }
+ return false;
}
//------------------------------------------------------------------
// This function locates all outputs associated with a given input (mixins)
@@ -2225,74 +2223,74 @@ bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const
// signature for each input.
bool Blockchain::check_tx_input(const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, std::vector<crypto::public_key> &output_keys, uint64_t* pmax_related_block_height)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
-
- // ND:
- // 1. Disable locking and make method private.
- //CRITICAL_REGION_LOCAL(m_blockchain_lock);
-
- struct outputs_visitor
- {
- std::vector<crypto::public_key >& m_output_keys;
- const Blockchain& m_bch;
- outputs_visitor(std::vector<crypto::public_key>& output_keys, const Blockchain& bch) :
- m_output_keys(output_keys), m_bch(bch)
- {
- }
- bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey)
- {
- //check tx unlock time
- if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
- {
- LOG_PRINT_L1("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
- return false;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
- m_output_keys.push_back(pubkey);
- return true;
- }
- };
+ // ND:
+ // 1. Disable locking and make method private.
+ //CRITICAL_REGION_LOCAL(m_blockchain_lock);
- output_keys.clear();
-
- //check ring signature
- outputs_visitor vi(output_keys, *this);
- if (!scan_outputkeys_for_indexes(txin, vi, tx_prefix_hash, pmax_related_block_height))
+ struct outputs_visitor
+ {
+ std::vector<crypto::public_key >& m_output_keys;
+ const Blockchain& m_bch;
+ outputs_visitor(std::vector<crypto::public_key>& output_keys, const Blockchain& bch) :
+ m_output_keys(output_keys), m_bch(bch)
{
- LOG_PRINT_L1("Failed to get output keys for tx with amount = " << print_money(txin.amount) << " and count indexes " << txin.key_offsets.size());
- return false;
}
-
- if(txin.key_offsets.size() != output_keys.size())
+ bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey)
{
- LOG_PRINT_L1("Output keys for tx with amount = " << txin.amount << " and count indexes " << txin.key_offsets.size() << " returned wrong keys count " << output_keys.size());
+ //check tx unlock time
+ if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
+ {
+ LOG_PRINT_L1("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
return false;
+ }
+
+ m_output_keys.push_back(pubkey);
+ return true;
}
- CHECK_AND_ASSERT_MES(sig.size() == output_keys.size(), false, "internal error: tx signatures count=" << sig.size() << " mismatch with outputs keys count for inputs=" << output_keys.size());
- return true;
+ };
+
+ output_keys.clear();
+
+ //check ring signature
+ outputs_visitor vi(output_keys, *this);
+ if (!scan_outputkeys_for_indexes(txin, vi, tx_prefix_hash, pmax_related_block_height))
+ {
+ LOG_PRINT_L1("Failed to get output keys for tx with amount = " << print_money(txin.amount) << " and count indexes " << txin.key_offsets.size());
+ return false;
+ }
+
+ if(txin.key_offsets.size() != output_keys.size())
+ {
+ LOG_PRINT_L1("Output keys for tx with amount = " << txin.amount << " and count indexes " << txin.key_offsets.size() << " returned wrong keys count " << output_keys.size());
+ return false;
+ }
+ CHECK_AND_ASSERT_MES(sig.size() == output_keys.size(), false, "internal error: tx signatures count=" << sig.size() << " mismatch with outputs keys count for inputs=" << output_keys.size());
+ return true;
}
//------------------------------------------------------------------
//TODO: Is this intended to do something else? Need to look into the todo there.
uint64_t Blockchain::get_adjusted_time() const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- //TODO: add collecting median time
- return time(NULL);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ //TODO: add collecting median time
+ return time(NULL);
}
//------------------------------------------------------------------
//TODO: revisit, has changed a bit on upstream
bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- uint64_t median_ts = epee::misc_utils::median(timestamps);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ uint64_t median_ts = epee::misc_utils::median(timestamps);
- if(b.timestamp < median_ts)
- {
- LOG_PRINT_L1("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts);
- return false;
- }
+ if(b.timestamp < median_ts)
+ {
+ LOG_PRINT_L1("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts);
+ return false;
+ }
- return true;
+ return true;
}
//------------------------------------------------------------------
// This function grabs the timestamps from the most recent <n> blocks,
@@ -2304,30 +2302,30 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
// false otherwise
bool Blockchain::check_block_timestamp(const block& b) const
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- if(b.timestamp > get_adjusted_time() + CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT)
- {
- LOG_PRINT_L1("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours");
- return false;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ if(b.timestamp > get_adjusted_time() + CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT)
+ {
+ LOG_PRINT_L1("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours");
+ return false;
+ }
- // if not enough blocks, no proper median yet, return true
- if(m_db->height() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
- {
- return true;
- }
+ // if not enough blocks, no proper median yet, return true
+ if(m_db->height() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
+ {
+ return true;
+ }
- std::vector<uint64_t> timestamps;
- auto h = m_db->height();
+ std::vector<uint64_t> timestamps;
+ auto h = m_db->height();
- // need most recent 60 blocks, get index of first of those
- size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
- for(;offset < h; ++offset)
- {
- timestamps.push_back(m_db->get_block_timestamp(offset));
- }
+ // need most recent 60 blocks, get index of first of those
+ size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
+ for(;offset < h; ++offset)
+ {
+ timestamps.push_back(m_db->get_block_timestamp(offset));
+ }
- return check_block_timestamp(timestamps, b);
+ return check_block_timestamp(timestamps, b);
}
//------------------------------------------------------------------
// Needs to validate the block and acquire each transaction from the
@@ -2335,394 +2333,394 @@ bool Blockchain::check_block_timestamp(const block& b) const
// m_db->add_block()
bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
-
- TIME_MEASURE_START(block_processing_time);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- TIME_MEASURE_START(t1);
-
- // this is a cheap test
- if (!m_hardfork->check(bl))
- {
- LOG_PRINT_L1("Block with id: " << id << std::endl << "has old version: " << (unsigned)bl.major_version << std::endl << "current: " << (unsigned)m_hardfork->get_current_version());
- return false;
- }
-
- if(bl.prev_id != get_tail_id())
- {
- LOG_PRINT_L1("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << get_tail_id());
- return false;
- }
-
- TIME_MEASURE_FINISH(t1);
- TIME_MEASURE_START(t2);
-
- // make sure block timestamp is not less than the median timestamp
- // of a set number of the most recent blocks.
- if(!check_block_timestamp(bl))
- {
- LOG_PRINT_L1("Block with id: " << id << std::endl << "has invalid timestamp: " << bl.timestamp);
- bvc.m_verifivation_failed = true;
- return false;
- }
-
- TIME_MEASURE_FINISH(t2);
- //check proof of work
- TIME_MEASURE_START(target_calculating_time);
+ LOG_PRINT_L3("Blockchain::" << __func__);
- // get the target difficulty for the block.
- // the calculation can overflow, among other failure cases,
- // so we need to check the return type.
- // FIXME: get_difficulty_for_next_block can also assert, look into
- // changing this to throwing exceptions instead so we can clean up.
- difficulty_type current_diffic = get_difficulty_for_next_block();
- CHECK_AND_ASSERT_MES(current_diffic, false, "!!!!!!!!! difficulty overhead !!!!!!!!!");
+ TIME_MEASURE_START(block_processing_time);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ TIME_MEASURE_START(t1);
- TIME_MEASURE_FINISH(target_calculating_time);
+ // this is a cheap test
+ if (!m_hardfork->check(bl))
+ {
+ LOG_PRINT_L1("Block with id: " << id << std::endl << "has old version: " << (unsigned)bl.major_version << std::endl << "current: " << (unsigned)m_hardfork->get_current_version());
+ return false;
+ }
- TIME_MEASURE_START(longhash_calculating_time);
+ if(bl.prev_id != get_tail_id())
+ {
+ LOG_PRINT_L1("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << get_tail_id());
+ return false;
+ }
- crypto::hash proof_of_work = null_hash;
+ TIME_MEASURE_FINISH(t1);
+ TIME_MEASURE_START(t2);
- // Formerly the code below contained an if loop with the following condition
- // !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())
- // however, this caused the daemon to not bother checking PoW for blocks
- // before checkpoints, which is very dangerous behaviour. We moved the PoW
- // validation out of the next chunk of code to make sure that we correctly
- // check PoW now.
- // FIXME: height parameter is not used...should it be used or should it not
- // be a parameter?
- // validate proof_of_work versus difficulty target
- bool precomputed = false;
+ // make sure block timestamp is not less than the median timestamp
+ // of a set number of the most recent blocks.
+ if(!check_block_timestamp(bl))
+ {
+ LOG_PRINT_L1("Block with id: " << id << std::endl << "has invalid timestamp: " << bl.timestamp);
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+
+ TIME_MEASURE_FINISH(t2);
+ //check proof of work
+ TIME_MEASURE_START(target_calculating_time);
+
+ // get the target difficulty for the block.
+ // the calculation can overflow, among other failure cases,
+ // so we need to check the return type.
+ // FIXME: get_difficulty_for_next_block can also assert, look into
+ // changing this to throwing exceptions instead so we can clean up.
+ difficulty_type current_diffic = get_difficulty_for_next_block();
+ CHECK_AND_ASSERT_MES(current_diffic, false, "!!!!!!!!! difficulty overhead !!!!!!!!!");
+
+ TIME_MEASURE_FINISH(target_calculating_time);
+
+ TIME_MEASURE_START(longhash_calculating_time);
+
+ crypto::hash proof_of_work = null_hash;
+
+ // Formerly the code below contained an if loop with the following condition
+ // !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())
+ // however, this caused the daemon to not bother checking PoW for blocks
+ // before checkpoints, which is very dangerous behaviour. We moved the PoW
+ // validation out of the next chunk of code to make sure that we correctly
+ // check PoW now.
+ // FIXME: height parameter is not used...should it be used or should it not
+ // be a parameter?
+ // validate proof_of_work versus difficulty target
+ bool precomputed = false;
#if defined(PER_BLOCK_CHECKPOINT)
- bool fast_check = false;
- if (m_db->height() < m_blocks_hash_check.size())
+ bool fast_check = false;
+ if (m_db->height() < m_blocks_hash_check.size())
+ {
+ auto hash = get_block_hash(bl);
+ if (memcmp(&hash, &m_blocks_hash_check[m_db->height()], sizeof(hash)) != 0)
+ {
+ LOG_PRINT_L1("Block with id is INVALID: " << id);
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+ fast_check = true;
+ }
+ else
+#endif
+ {
+ auto it = m_blocks_longhash_table.find(id);
+ if (it != m_blocks_longhash_table.end())
{
- auto hash = get_block_hash(bl);
- if (memcmp(&hash, &m_blocks_hash_check[m_db->height()], sizeof(hash)) != 0)
- {
- LOG_PRINT_L1("Block with id is INVALID: " << id);
- bvc.m_verifivation_failed = true;
- return false;
- }
- fast_check = true;
+ precomputed = true;
+ proof_of_work = it->second;
}
else
-#endif
- {
- auto it = m_blocks_longhash_table.find(id);
- if (it != m_blocks_longhash_table.end())
- {
- precomputed = true;
- proof_of_work = it->second;
- }
- else
- proof_of_work = get_block_longhash(bl, m_db->height());
+ proof_of_work = get_block_longhash(bl, m_db->height());
- // validate proof_of_work versus difficulty target
- if(!check_hash(proof_of_work, current_diffic))
- {
- LOG_PRINT_L1("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << std::endl << "unexpected difficulty: " << current_diffic);
- bvc.m_verifivation_failed = true;
- return false;
- }
+ // validate proof_of_work versus difficulty target
+ if(!check_hash(proof_of_work, current_diffic))
+ {
+ LOG_PRINT_L1("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << std::endl << "unexpected difficulty: " << current_diffic);
+ bvc.m_verifivation_failed = true;
+ return false;
}
+ }
- // If we're at a checkpoint, ensure that our hardcoded checkpoint hash
- // is correct.
- if(m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()))
+ // If we're at a checkpoint, ensure that our hardcoded checkpoint hash
+ // is correct.
+ if(m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()))
+ {
+ if(!m_checkpoints.check_block(get_current_blockchain_height(), id))
{
- if(!m_checkpoints.check_block(get_current_blockchain_height(), id))
- {
- LOG_ERROR("CHECKPOINT VALIDATION FAILED");
- bvc.m_verifivation_failed = true;
- return false;
- }
+ LOG_ERROR("CHECKPOINT VALIDATION FAILED");
+ bvc.m_verifivation_failed = true;
+ return false;
}
+ }
- TIME_MEASURE_FINISH(longhash_calculating_time);
- if (precomputed)
- longhash_calculating_time += m_fake_pow_calc_time;
+ TIME_MEASURE_FINISH(longhash_calculating_time);
+ if (precomputed)
+ longhash_calculating_time += m_fake_pow_calc_time;
- TIME_MEASURE_START(t3);
+ TIME_MEASURE_START(t3);
- // sanity check basic miner tx properties;
- if(!prevalidate_miner_transaction(bl, m_db->height()))
- {
- LOG_PRINT_L1("Block with id: " << id << " failed to pass prevalidation");
- bvc.m_verifivation_failed = true;
- return false;
- }
+ // sanity check basic miner tx properties;
+ if(!prevalidate_miner_transaction(bl, m_db->height()))
+ {
+ LOG_PRINT_L1("Block with id: " << id << " failed to pass prevalidation");
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
- size_t coinbase_blob_size = get_object_blobsize(bl.miner_tx);
- size_t cumulative_block_size = coinbase_blob_size;
+ size_t coinbase_blob_size = get_object_blobsize(bl.miner_tx);
+ size_t cumulative_block_size = coinbase_blob_size;
- std::vector<transaction> txs;
- key_images_container keys;
+ std::vector<transaction> txs;
+ key_images_container keys;
- uint64_t fee_summary = 0;
- uint64_t t_checktx = 0;
- uint64_t t_exists = 0;
- uint64_t t_pool = 0;
- uint64_t t_dblspnd = 0;
- bool add_tx_to_pool = false;
- TIME_MEASURE_FINISH(t3);
+ uint64_t fee_summary = 0;
+ uint64_t t_checktx = 0;
+ uint64_t t_exists = 0;
+ uint64_t t_pool = 0;
+ uint64_t t_dblspnd = 0;
+ bool add_tx_to_pool = false;
+ TIME_MEASURE_FINISH(t3);
// XXX old code adds miner tx here
- int tx_index = 0;
- // Iterate over the block's transaction hashes, grabbing each
- // from the tx_pool and validating them. Each is then added
- // to txs. Keys spent in each are added to <keys> by the double spend check.
- for (const crypto::hash& tx_id : bl.tx_hashes)
- {
- transaction tx;
- size_t blob_size = 0;
- uint64_t fee = 0;
- bool relayed = false;
- TIME_MEASURE_START(aa);
+ int tx_index = 0;
+ // Iterate over the block's transaction hashes, grabbing each
+ // from the tx_pool and validating them. Each is then added
+ // to txs. Keys spent in each are added to <keys> by the double spend check.
+ for (const crypto::hash& tx_id : bl.tx_hashes)
+ {
+ transaction tx;
+ size_t blob_size = 0;
+ uint64_t fee = 0;
+ bool relayed = false;
+ TIME_MEASURE_START(aa);
// XXX old code does not check whether tx exists
- if (m_db->tx_exists(tx_id))
- {
- LOG_PRINT_L1("Block with id: " << id << " attempting to add transaction already in blockchain with id: " << tx_id);
- bvc.m_verifivation_failed = true;
- break;
- }
+ if (m_db->tx_exists(tx_id))
+ {
+ LOG_PRINT_L1("Block with id: " << id << " attempting to add transaction already in blockchain with id: " << tx_id);
+ bvc.m_verifivation_failed = true;
+ break;
+ }
- TIME_MEASURE_FINISH(aa);
- t_exists += aa;
- TIME_MEASURE_START(bb);
+ TIME_MEASURE_FINISH(aa);
+ t_exists += aa;
+ TIME_MEASURE_START(bb);
- // get transaction with hash <tx_id> from tx_pool
- if(!m_tx_pool.take_tx(tx_id, tx, blob_size, fee, relayed))
- {
- LOG_PRINT_L1("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
- bvc.m_verifivation_failed = true;
- break;
- }
+ // get transaction with hash <tx_id> from tx_pool
+ if(!m_tx_pool.take_tx(tx_id, tx, blob_size, fee, relayed))
+ {
+ LOG_PRINT_L1("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
+ bvc.m_verifivation_failed = true;
+ break;
+ }
+
+ TIME_MEASURE_FINISH(bb);
+ t_pool += bb;
+ // add the transaction to the temp list of transactions, so we can either
+ // store the list of transactions all at once or return the ones we've
+ // taken from the tx_pool back to it if the block fails verification.
+ txs.push_back(tx);
+ TIME_MEASURE_START(dd);
- TIME_MEASURE_FINISH(bb);
- t_pool += bb;
- // add the transaction to the temp list of transactions, so we can either
- // store the list of transactions all at once or return the ones we've
- // taken from the tx_pool back to it if the block fails verification.
- txs.push_back(tx);
- TIME_MEASURE_START(dd);
-
- // ND: this is not needed, db->add_block() checks for duplicate k_images and fails accordingly.
- // if (!check_for_double_spend(tx, keys))
- // {
- // LOG_PRINT_L0("Double spend detected in transaction (id: " << tx_id);
- // bvc.m_verifivation_failed = true;
- // break;
- // }
-
- TIME_MEASURE_FINISH(dd);
- t_dblspnd += dd;
- TIME_MEASURE_START(cc);
+ // ND: this is not needed, db->add_block() checks for duplicate k_images and fails accordingly.
+ // if (!check_for_double_spend(tx, keys))
+ // {
+ // LOG_PRINT_L0("Double spend detected in transaction (id: " << tx_id);
+ // bvc.m_verifivation_failed = true;
+ // break;
+ // }
+
+ TIME_MEASURE_FINISH(dd);
+ t_dblspnd += dd;
+ TIME_MEASURE_START(cc);
#if defined(PER_BLOCK_CHECKPOINT)
- if (!fast_check)
+ if (!fast_check)
#endif
- {
- // validate that transaction inputs and the keys spending them are correct.
- if(!check_tx_inputs(tx))
- {
- LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
-
- //TODO: why is this done? make sure that keeping invalid blocks makes sense.
- add_block_as_invalid(bl, id);
- LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
- bvc.m_verifivation_failed = true;
- add_tx_to_pool = true;
- break;
- }
- }
-#if defined(PER_BLOCK_CHECKPOINT)
- else
- {
- // ND: if fast_check is enabled for blocks, there is no need to check
- // the transaction inputs, but do some sanity checks anyway.
- if (memcmp(&m_blocks_txs_check[tx_index++], &tx_id, sizeof(tx_id)) != 0)
- {
- LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
- //TODO: why is this done? make sure that keeping invalid blocks makes sense.
- add_block_as_invalid(bl, id);
- LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
- bvc.m_verifivation_failed = true;
- add_tx_to_pool = true;
- break;
- }
- }
-#endif
- TIME_MEASURE_FINISH(cc);
- t_checktx += cc;
- fee_summary += fee;
- cumulative_block_size += blob_size;
- }
-
- m_blocks_txs_check.clear();
+ {
+ // validate that transaction inputs and the keys spending them are correct.
+ if(!check_tx_inputs(tx))
+ {
+ LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
- TIME_MEASURE_START(vmt);
- uint64_t base_reward = 0;
- uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0;
- if(!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins))
+ //TODO: why is this done? make sure that keeping invalid blocks makes sense.
+ add_block_as_invalid(bl, id);
+ LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
+ bvc.m_verifivation_failed = true;
+ add_tx_to_pool = true;
+ break;
+ }
+ }
+#if defined(PER_BLOCK_CHECKPOINT)
+ else
{
- LOG_PRINT_L1("Block with id: " << id << " has incorrect miner transaction");
+ // ND: if fast_check is enabled for blocks, there is no need to check
+ // the transaction inputs, but do some sanity checks anyway.
+ if (memcmp(&m_blocks_txs_check[tx_index++], &tx_id, sizeof(tx_id)) != 0)
+ {
+ LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
+ //TODO: why is this done? make sure that keeping invalid blocks makes sense.
+ add_block_as_invalid(bl, id);
+ LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
bvc.m_verifivation_failed = true;
+ add_tx_to_pool = true;
+ break;
+ }
}
-
- TIME_MEASURE_FINISH(vmt);
- size_t block_size;
- difficulty_type cumulative_difficulty;
-
- // populate various metadata about the block to be stored alongside it.
- block_size = cumulative_block_size;
- cumulative_difficulty = current_diffic;
- already_generated_coins = already_generated_coins + base_reward;
- if(m_db->height())
- cumulative_difficulty += m_db->get_block_cumulative_difficulty(m_db->height() - 1);
-
- TIME_MEASURE_FINISH(block_processing_time);
- if(precomputed)
- block_processing_time += m_fake_pow_calc_time;
-
- TIME_MEASURE_START(addblock);
- uint64_t new_height = 0;
- bool add_success = true;
- if (!bvc.m_verifivation_failed)
+#endif
+ TIME_MEASURE_FINISH(cc);
+ t_checktx += cc;
+ fee_summary += fee;
+ cumulative_block_size += blob_size;
+ }
+
+ m_blocks_txs_check.clear();
+
+ TIME_MEASURE_START(vmt);
+ uint64_t base_reward = 0;
+ uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0;
+ if(!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins))
+ {
+ LOG_PRINT_L1("Block with id: " << id << " has incorrect miner transaction");
+ bvc.m_verifivation_failed = true;
+ }
+
+ TIME_MEASURE_FINISH(vmt);
+ size_t block_size;
+ difficulty_type cumulative_difficulty;
+
+ // populate various metadata about the block to be stored alongside it.
+ block_size = cumulative_block_size;
+ cumulative_difficulty = current_diffic;
+ already_generated_coins = already_generated_coins + base_reward;
+ if(m_db->height())
+ cumulative_difficulty += m_db->get_block_cumulative_difficulty(m_db->height() - 1);
+
+ TIME_MEASURE_FINISH(block_processing_time);
+ if(precomputed)
+ block_processing_time += m_fake_pow_calc_time;
+
+ TIME_MEASURE_START(addblock);
+ uint64_t new_height = 0;
+ bool add_success = true;
+ if (!bvc.m_verifivation_failed)
+ {
+ try
{
- try
- {
- new_height = m_db->add_block(bl, block_size, cumulative_difficulty, already_generated_coins, txs);
- }
- catch (const std::exception& e)
- {
- //TODO: figure out the best way to deal with this failure
- LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what());
- add_success = false;
- }
+ new_height = m_db->add_block(bl, block_size, cumulative_difficulty, already_generated_coins, txs);
}
-
- // if we failed for any reason to verify the block, return taken
- // transactions to the tx_pool.
- if ((bvc.m_verifivation_failed && add_tx_to_pool) || !add_success)
+ catch (const std::exception& e)
{
- // return taken transactions to transaction pool
- for (auto& tx : txs)
- {
- cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
- // We assume that if they were in a block, the transactions are already
- // known to the network as a whole. However, if we had mined that block,
- // that might not be always true. Unlikely though, and always relaying
- // these again might cause a spike of traffic as many nodes re-relay
- // all the transactions in a popped block when a reorg happens.
- if (!m_tx_pool.add_tx(tx, tvc, true, true))
- {
- LOG_PRINT_L0("Failed to return taken transaction with hash: " << get_transaction_hash(tx) << " to tx_pool");
- }
- }
- return false;
+ //TODO: figure out the best way to deal with this failure
+ LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what());
+ add_success = false;
+ }
+ }
+
+ // if we failed for any reason to verify the block, return taken
+ // transactions to the tx_pool.
+ if ((bvc.m_verifivation_failed && add_tx_to_pool) || !add_success)
+ {
+ // return taken transactions to transaction pool
+ for (auto& tx : txs)
+ {
+ cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
+ // We assume that if they were in a block, the transactions are already
+ // known to the network as a whole. However, if we had mined that block,
+ // that might not be always true. Unlikely though, and always relaying
+ // these again might cause a spike of traffic as many nodes re-relay
+ // all the transactions in a popped block when a reorg happens.
+ if (!m_tx_pool.add_tx(tx, tvc, true, true))
+ {
+ LOG_PRINT_L0("Failed to return taken transaction with hash: " << get_transaction_hash(tx) << " to tx_pool");
+ }
}
+ return false;
+ }
- TIME_MEASURE_FINISH(addblock);
+ TIME_MEASURE_FINISH(addblock);
- // this will not fail since check succeeded above
- m_hardfork->add(bl, new_height - 1);
+ // this will not fail since check succeeded above
+ m_hardfork->add(bl, new_height - 1);
- // do this after updating the hard fork state since the size limit may change due to fork
- update_next_cumulative_size_limit();
+ // do this after updating the hard fork state since the size limit may change due to fork
+ update_next_cumulative_size_limit();
- LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
- if(m_show_time_stats)
- {
- LOG_PRINT_L0("Height: " << new_height << " blob: " << coinbase_blob_size << " cumm: "
- << cumulative_block_size << " p/t: " << block_processing_time << " ("
- << target_calculating_time << "/" << longhash_calculating_time << "/"
- << t1 << "/" << t2 << "/" << t3 << "/" << t_exists << "/" << t_pool
- << "/" << t_checktx << "/" << t_dblspnd << "/" << vmt << "/" << addblock << ")ms");
- }
+ LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
+ if(m_show_time_stats)
+ {
+ LOG_PRINT_L0("Height: " << new_height << " blob: " << coinbase_blob_size << " cumm: "
+ << cumulative_block_size << " p/t: " << block_processing_time << " ("
+ << target_calculating_time << "/" << longhash_calculating_time << "/"
+ << t1 << "/" << t2 << "/" << t3 << "/" << t_exists << "/" << t_pool
+ << "/" << t_checktx << "/" << t_dblspnd << "/" << vmt << "/" << addblock << ")ms");
+ }
- bvc.m_added_to_main_chain = true;
- ++m_sync_counter;
+ bvc.m_added_to_main_chain = true;
+ ++m_sync_counter;
- // appears to be a NOP *and* is called elsewhere. wat?
- m_tx_pool.on_blockchain_inc(new_height, id);
+ // appears to be a NOP *and* is called elsewhere. wat?
+ m_tx_pool.on_blockchain_inc(new_height, id);
- return true;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::update_next_cumulative_size_limit()
{
- uint64_t full_reward_zone = get_current_hard_fork_version() < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE;
+ uint64_t full_reward_zone = get_current_hard_fork_version() < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE;
- LOG_PRINT_L3("Blockchain::" << __func__);
- std::vector<size_t> sz;
- get_last_n_blocks_sizes(sz, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ std::vector<size_t> sz;
+ get_last_n_blocks_sizes(sz, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
- uint64_t median = epee::misc_utils::median(sz);
- if(median <= full_reward_zone)
- median = full_reward_zone;
+ uint64_t median = epee::misc_utils::median(sz);
+ if(median <= full_reward_zone)
+ median = full_reward_zone;
- m_current_block_cumul_sz_limit = median*2;
- return true;
+ m_current_block_cumul_sz_limit = median*2;
+ return true;
}
//------------------------------------------------------------------
bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc)
{
- LOG_PRINT_L3("Blockchain::" << __func__);
- //copy block here to let modify block.target
- block bl = bl_;
- 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);
- if(have_block(id))
- {
- LOG_PRINT_L3("block with id = " << id << " already exists");
- bvc.m_already_exists = true;
- return false;
- }
+ LOG_PRINT_L3("Blockchain::" << __func__);
+ //copy block here to let modify block.target
+ block bl = bl_;
+ 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);
+ if(have_block(id))
+ {
+ LOG_PRINT_L3("block with id = " << id << " already exists");
+ bvc.m_already_exists = true;
+ return false;
+ }
- //check that block refers to chain tail
- if(!(bl.prev_id == get_tail_id()))
- {
- //chain switching or wrong block
- bvc.m_added_to_main_chain = false;
- return handle_alternative_block(bl, id, bvc);
- //never relay alternative blocks
- }
+ //check that block refers to chain tail
+ if(!(bl.prev_id == get_tail_id()))
+ {
+ //chain switching or wrong block
+ bvc.m_added_to_main_chain = false;
+ return handle_alternative_block(bl, id, bvc);
+ //never relay alternative blocks
+ }
- return handle_block_to_main_chain(bl, id, bvc);
+ return handle_block_to_main_chain(bl, id, bvc);
}
//------------------------------------------------------------------
void Blockchain::check_against_checkpoints(const checkpoints& points, bool enforce)
{
- const auto& pts = points.get_points();
+ const auto& pts = points.get_points();
- for (const auto& pt : pts)
+ for (const auto& pt : pts)
+ {
+ // if the checkpoint is for a block we don't have yet, move on
+ if (pt.first >= m_db->height())
{
- // if the checkpoint is for a block we don't have yet, move on
- if (pt.first >= m_db->height())
- {
- continue;
- }
+ continue;
+ }
- if (!points.check_block(pt.first, m_db->get_block_hash_from_height(pt.first)))
- {
- // if asked to enforce checkpoints, roll back to a couple of blocks before the checkpoint
- if (enforce)
- {
- LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!");
- std::list<block> empty;
- rollback_blockchain_switching(empty, pt.first - 2);
- }
- else
- {
- LOG_ERROR("WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option");
- }
- }
+ if (!points.check_block(pt.first, m_db->get_block_hash_from_height(pt.first)))
+ {
+ // if asked to enforce checkpoints, roll back to a couple of blocks before the checkpoint
+ if (enforce)
+ {
+ LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!");
+ std::list<block> empty;
+ rollback_blockchain_switching(empty, pt.first - 2);
+ }
+ else
+ {
+ LOG_ERROR("WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option");
+ }
}
+ }
}
//------------------------------------------------------------------
// returns false if any of the checkpoints loading returns false.
@@ -2730,119 +2728,119 @@ void Blockchain::check_against_checkpoints(const checkpoints& points, bool enfor
// with an existing checkpoint.
bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns)
{
- if (!cryptonote::load_checkpoints_from_json(m_checkpoints, file_path))
+ if (!cryptonote::load_checkpoints_from_json(m_checkpoints, file_path))
+ {
+ return false;
+ }
+
+ // if we're checking both dns and json, load checkpoints from dns.
+ // if we're not hard-enforcing dns checkpoints, handle accordingly
+ if (m_enforce_dns_checkpoints && check_dns)
+ {
+ if (!cryptonote::load_checkpoints_from_dns(m_checkpoints))
{
- return false;
+ return false;
}
-
- // if we're checking both dns and json, load checkpoints from dns.
- // if we're not hard-enforcing dns checkpoints, handle accordingly
- if (m_enforce_dns_checkpoints && check_dns)
+ }
+ else if (check_dns)
+ {
+ checkpoints dns_points;
+ cryptonote::load_checkpoints_from_dns(dns_points);
+ if (m_checkpoints.check_for_conflicts(dns_points))
{
- if (!cryptonote::load_checkpoints_from_dns(m_checkpoints))
- {
- return false;
- }
+ check_against_checkpoints(dns_points, false);
}
- else if (check_dns)
+ else
{
- checkpoints dns_points;
- cryptonote::load_checkpoints_from_dns(dns_points);
- if (m_checkpoints.check_for_conflicts(dns_points))
- {
- check_against_checkpoints(dns_points, false);
- }
- else
- {
- LOG_PRINT_L0("One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
- }
+ LOG_PRINT_L0("One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
}
+ }
- check_against_checkpoints(m_checkpoints, true);
+ check_against_checkpoints(m_checkpoints, true);
- return true;
+ return true;
}
//------------------------------------------------------------------
void Blockchain::set_enforce_dns_checkpoints(bool enforce_checkpoints)
{
- m_enforce_dns_checkpoints = enforce_checkpoints;
+ m_enforce_dns_checkpoints = enforce_checkpoints;
}
//------------------------------------------------------------------
void Blockchain::block_longhash_worker(const uint64_t height, const std::vector<block> &blocks, std::unordered_map<crypto::hash, crypto::hash> &map) const
{
- TIME_MEASURE_START(t);
- slow_hash_allocate_state();
+ TIME_MEASURE_START(t);
+ slow_hash_allocate_state();
- for (const auto & block : blocks)
- {
- crypto::hash id = get_block_hash(block);
- crypto::hash pow = get_block_longhash(block, height);
- map.emplace(id, pow);
- }
+ for (const auto & block : blocks)
+ {
+ crypto::hash id = get_block_hash(block);
+ crypto::hash pow = get_block_longhash(block, height);
+ map.emplace(id, pow);
+ }
- slow_hash_free_state();
- TIME_MEASURE_FINISH(t);
+ slow_hash_free_state();
+ TIME_MEASURE_FINISH(t);
}
//------------------------------------------------------------------
bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync)
{
- LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
- TIME_MEASURE_START(t1);
+ LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ TIME_MEASURE_START(t1);
- if (m_sync_counter > 0)
+ if (m_sync_counter > 0)
+ {
+ if (force_sync)
{
- if (force_sync)
- {
- if(m_db_sync_mode != db_nosync)
- store_blockchain();
- m_sync_counter = 0;
- }
- else if (m_sync_counter >= m_db_blocks_per_sync)
- {
- if(m_db_sync_mode == db_async)
- {
- m_sync_counter = 0;
- m_async_service.dispatch(boost::bind(&Blockchain::store_blockchain, this));
- }
- else if(m_db_sync_mode == db_sync)
- {
- store_blockchain();
- }
- else // db_nosync
- {
- // DO NOTHING, not required to call sync.
- }
- }
+ if(m_db_sync_mode != db_nosync)
+ store_blockchain();
+ m_sync_counter = 0;
}
+ else if (m_sync_counter >= m_db_blocks_per_sync)
+ {
+ if(m_db_sync_mode == db_async)
+ {
+ m_sync_counter = 0;
+ m_async_service.dispatch(boost::bind(&Blockchain::store_blockchain, this));
+ }
+ else if(m_db_sync_mode == db_sync)
+ {
+ store_blockchain();
+ }
+ else // db_nosync
+ {
+ // DO NOTHING, not required to call sync.
+ }
+ }
+ }
- TIME_MEASURE_FINISH(t1);
- m_blocks_longhash_table.clear();
- m_scan_table.clear();
- m_check_tx_inputs_table.clear();
- m_blocks_txs_check.clear();
- m_check_txin_table.clear();
+ TIME_MEASURE_FINISH(t1);
+ m_blocks_longhash_table.clear();
+ m_scan_table.clear();
+ m_check_tx_inputs_table.clear();
+ m_blocks_txs_check.clear();
+ m_check_txin_table.clear();
- return true;
+ return true;
}
//------------------------------------------------------------------
void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, std::unordered_map<crypto::hash, cryptonote::transaction> &txs) const
{
- try
- {
- m_db->get_output_key(amount, offsets, outputs);
- }
- catch (const std::exception& e)
- {
- LOG_PRINT_L1("EXCEPTION: " << e.what());
- }
- catch (...)
- {
+ try
+ {
+ m_db->get_output_key(amount, offsets, outputs);
+ }
+ catch (const std::exception& e)
+ {
+ LOG_PRINT_L1("EXCEPTION: " << e.what());
+ }
+ catch (...)
+ {
- }
+ }
}
//------------------------------------------------------------------
@@ -2854,137 +2852,137 @@ void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uin
// keys.
bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_entry> &blocks_entry)
{
- LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
- TIME_MEASURE_START(prepare);
- CRITICAL_REGION_LOCAL(m_blockchain_lock);
+ LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
+ TIME_MEASURE_START(prepare);
+ CRITICAL_REGION_LOCAL(m_blockchain_lock);
- if(blocks_entry.size() == 0)
- return false;
+ if(blocks_entry.size() == 0)
+ return false;
- if ((m_db->height() + blocks_entry.size()) < m_blocks_hash_check.size())
- return true;
+ if ((m_db->height() + blocks_entry.size()) < m_blocks_hash_check.size())
+ return true;
- bool blocks_exist = false;
- uint64_t threads = std::thread::hardware_concurrency();
+ bool blocks_exist = false;
+ uint64_t threads = std::thread::hardware_concurrency();
- if (blocks_entry.size() > 1 && threads > 1 && m_max_prepare_blocks_threads > 1)
- {
- // limit threads, default limit = 4
- if(threads > m_max_prepare_blocks_threads)
- threads = m_max_prepare_blocks_threads;
+ if (blocks_entry.size() > 1 && threads > 1 && m_max_prepare_blocks_threads > 1)
+ {
+ // limit threads, default limit = 4
+ if(threads > m_max_prepare_blocks_threads)
+ threads = m_max_prepare_blocks_threads;
- uint64_t height = m_db->height();
- std::vector<boost::thread *> thread_list;
- int batches = blocks_entry.size() / threads;
- int extra = blocks_entry.size() % threads;
- LOG_PRINT_L1("block_batches: " << batches);
- std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
- std::vector < std::vector < block >> blocks(threads);
- auto it = blocks_entry.begin();
+ uint64_t height = m_db->height();
+ std::vector<boost::thread *> thread_list;
+ int batches = blocks_entry.size() / threads;
+ int extra = blocks_entry.size() % threads;
+ LOG_PRINT_L1("block_batches: " << batches);
+ std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
+ std::vector < std::vector < block >> blocks(threads);
+ auto it = blocks_entry.begin();
+
+ for (uint64_t i = 0; i < threads; i++)
+ {
+ for (int j = 0; j < batches; j++)
+ {
+ block block;
- for (uint64_t i = 0; i < threads; i++)
+ if (!parse_and_validate_block_from_blob(it->block, block))
{
- for (int j = 0; j < batches; j++)
- {
- block block;
-
- if (!parse_and_validate_block_from_blob(it->block, block))
- {
- std::advance(it, 1);
- continue;
- }
-
- // check first block and skip all blocks if its not chained properly
- if (i == 0 && j == 0)
- {
- crypto::hash tophash = m_db->top_block_hash();
- if (block.prev_id != tophash)
- {
- LOG_PRINT_L1("Skipping prepare blocks. New blocks don't belong to chain.")
- return true;
- }
- }
- if (have_block(get_block_hash(block)))
- {
- blocks_exist = true;
- break;
- }
-
- blocks[i].push_back(block);
- std::advance(it, 1);
- }
+ std::advance(it, 1);
+ continue;
}
- for (int i = 0; i < extra && !blocks_exist; i++)
+ // check first block and skip all blocks if its not chained properly
+ if (i == 0 && j == 0)
{
- block block;
-
- if (!parse_and_validate_block_from_blob(it->block, block))
- {
- std::advance(it, 1);
- continue;
- }
-
- if (have_block(get_block_hash(block)))
- {
- blocks_exist = true;
- break;
- }
-
- blocks[i].push_back(block);
- std::advance(it, 1);
+ crypto::hash tophash = m_db->top_block_hash();
+ if (block.prev_id != tophash)
+ {
+ LOG_PRINT_L1("Skipping prepare blocks. New blocks don't belong to chain.")
+ return true;
+ }
}
-
- if (!blocks_exist)
+ if (have_block(get_block_hash(block)))
{
- m_blocks_longhash_table.clear();
- for (uint64_t i = 0; i < threads; i++)
- {
- thread_list.push_back(new boost::thread(&Blockchain::block_longhash_worker, this, height + (i * batches), std::cref(blocks[i]), std::ref(maps[i])));
- }
+ blocks_exist = true;
+ break;
+ }
- for (size_t j = 0; j < thread_list.size(); j++)
- {
- thread_list[j]->join();
- delete thread_list[j];
- }
+ blocks[i].push_back(block);
+ std::advance(it, 1);
+ }
+ }
- thread_list.clear();
+ for (int i = 0; i < extra && !blocks_exist; i++)
+ {
+ block block;
- for (const auto & map : maps)
- {
- m_blocks_longhash_table.insert(map.begin(), map.end());
- }
- }
+ if (!parse_and_validate_block_from_blob(it->block, block))
+ {
+ std::advance(it, 1);
+ continue;
+ }
+
+ if (have_block(get_block_hash(block)))
+ {
+ blocks_exist = true;
+ break;
+ }
+
+ blocks[i].push_back(block);
+ std::advance(it, 1);
}
- if (blocks_exist)
+ if (!blocks_exist)
{
- LOG_PRINT_L0("Skipping prepare blocks. Blocks exist.")
- return true;
+ m_blocks_longhash_table.clear();
+ for (uint64_t i = 0; i < threads; i++)
+ {
+ thread_list.push_back(new boost::thread(&Blockchain::block_longhash_worker, this, height + (i * batches), std::cref(blocks[i]), std::ref(maps[i])));
+ }
+
+ for (size_t j = 0; j < thread_list.size(); j++)
+ {
+ thread_list[j]->join();
+ delete thread_list[j];
+ }
+
+ thread_list.clear();
+
+ for (const auto & map : maps)
+ {
+ m_blocks_longhash_table.insert(map.begin(), map.end());
+ }
}
+ }
- m_fake_scan_time = 0;
- m_fake_pow_calc_time = 0;
+ if (blocks_exist)
+ {
+ LOG_PRINT_L0("Skipping prepare blocks. Blocks exist.")
+ return true;
+ }
- m_scan_table.clear();
- m_check_tx_inputs_table.clear();
- m_check_txin_table.clear();
+ m_fake_scan_time = 0;
+ m_fake_pow_calc_time = 0;
- TIME_MEASURE_FINISH(prepare);
- m_fake_pow_calc_time = prepare / blocks_entry.size();
+ m_scan_table.clear();
+ m_check_tx_inputs_table.clear();
+ m_check_txin_table.clear();
- if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
- LOG_PRINT_L0("Prepare blocks took: " << prepare << " ms");
+ TIME_MEASURE_FINISH(prepare);
+ m_fake_pow_calc_time = prepare / blocks_entry.size();
- TIME_MEASURE_START(scantable);
+ if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
+ LOG_PRINT_L0("Prepare blocks took: " << prepare << " ms");
- // [input] stores all unique amounts found
- std::vector < uint64_t > amounts;
- // [input] stores all absolute_offsets for each amount
- std::map<uint64_t, std::vector<uint64_t>> offset_map;
- // [output] stores all output_data_t for each absolute_offset
- std::map<uint64_t, std::vector<output_data_t>> tx_map;
+ TIME_MEASURE_START(scantable);
+
+ // [input] stores all unique amounts found
+ std::vector < uint64_t > amounts;
+ // [input] stores all absolute_offsets for each amount
+ std::map<uint64_t, std::vector<uint64_t>> offset_map;
+ // [output] stores all output_data_t for each absolute_offset
+ std::map<uint64_t, std::vector<output_data_t>> tx_map;
#define SCAN_TABLE_QUIT(m) \
do { \
@@ -2993,191 +2991,191 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
return false; \
} while(0); \
- // generate sorted tables for all amounts and absolute offsets
- for (const auto &entry : blocks_entry)
+ // generate sorted tables for all amounts and absolute offsets
+ for (const auto &entry : blocks_entry)
+ {
+ for (const auto &tx_blob : entry.txs)
{
- for (const auto &tx_blob : entry.txs)
- {
- crypto::hash tx_hash = null_hash;
- crypto::hash tx_prefix_hash = null_hash;
- transaction tx;
+ crypto::hash tx_hash = null_hash;
+ crypto::hash tx_prefix_hash = null_hash;
+ transaction tx;
- if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash))
- SCAN_TABLE_QUIT("Could not parse tx from incoming blocks.");
+ if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash))
+ SCAN_TABLE_QUIT("Could not parse tx from incoming blocks.");
- auto its = m_scan_table.find(tx_prefix_hash);
- if (its != m_scan_table.end())
- SCAN_TABLE_QUIT("Duplicate tx found from incoming blocks.");
+ auto its = m_scan_table.find(tx_prefix_hash);
+ if (its != m_scan_table.end())
+ SCAN_TABLE_QUIT("Duplicate tx found from incoming blocks.");
- m_scan_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, std::vector<output_data_t>>());
- its = m_scan_table.find(tx_prefix_hash);
- assert(its != m_scan_table.end());
+ m_scan_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, std::vector<output_data_t>>());
+ its = m_scan_table.find(tx_prefix_hash);
+ assert(its != m_scan_table.end());
- // get all amounts from tx.vin(s)
- for (const auto &txin : tx.vin)
- {
- const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
+ // get all amounts from tx.vin(s)
+ for (const auto &txin : tx.vin)
+ {
+ const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
- // check for duplicate
- auto it = its->second.find(in_to_key.k_image);
- if (it != its->second.end())
- SCAN_TABLE_QUIT("Duplicate key_image found from incoming blocks.");
+ // check for duplicate
+ auto it = its->second.find(in_to_key.k_image);
+ if (it != its->second.end())
+ SCAN_TABLE_QUIT("Duplicate key_image found from incoming blocks.");
- amounts.push_back(in_to_key.amount);
- }
+ amounts.push_back(in_to_key.amount);
+ }
- // sort and remove duplicate amounts from amounts list
- std::sort(amounts.begin(), amounts.end());
- auto last = std::unique(amounts.begin(), amounts.end());
- amounts.erase(last, amounts.end());
+ // sort and remove duplicate amounts from amounts list
+ std::sort(amounts.begin(), amounts.end());
+ auto last = std::unique(amounts.begin(), amounts.end());
+ amounts.erase(last, amounts.end());
- // add amount to the offset_map and tx_map
- for (const uint64_t &amount : amounts)
- {
- if (offset_map.find(amount) == offset_map.end())
- offset_map.emplace(amount, std::vector<uint64_t>());
+ // add amount to the offset_map and tx_map
+ for (const uint64_t &amount : amounts)
+ {
+ if (offset_map.find(amount) == offset_map.end())
+ offset_map.emplace(amount, std::vector<uint64_t>());
- if (tx_map.find(amount) == tx_map.end())
- tx_map.emplace(amount, std::vector<output_data_t>());
- }
+ if (tx_map.find(amount) == tx_map.end())
+ tx_map.emplace(amount, std::vector<output_data_t>());
+ }
- // add new absolute_offsets to offset_map
- for (const auto &txin : tx.vin)
- {
- const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
- // no need to check for duplicate here.
- auto absolute_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
- for (const auto & offset : absolute_offsets)
- offset_map[in_to_key.amount].push_back(offset);
+ // add new absolute_offsets to offset_map
+ for (const auto &txin : tx.vin)
+ {
+ const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
+ // no need to check for duplicate here.
+ auto absolute_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
+ for (const auto & offset : absolute_offsets)
+ offset_map[in_to_key.amount].push_back(offset);
- }
+ }
- // sort and remove duplicate absolute_offsets in offset_map
- for (auto &offsets : offset_map)
- {
- std::sort(offsets.second.begin(), offsets.second.end());
- auto last = std::unique(offsets.second.begin(), offsets.second.end());
- offsets.second.erase(last, offsets.second.end());
- }
- }
+ // sort and remove duplicate absolute_offsets in offset_map
+ for (auto &offsets : offset_map)
+ {
+ std::sort(offsets.second.begin(), offsets.second.end());
+ auto last = std::unique(offsets.second.begin(), offsets.second.end());
+ offsets.second.erase(last, offsets.second.end());
+ }
}
+ }
- // [output] stores all transactions for each tx_out_index::hash found
- std::vector<std::unordered_map<crypto::hash, cryptonote::transaction>> transactions(amounts.size());
+ // [output] stores all transactions for each tx_out_index::hash found
+ std::vector<std::unordered_map<crypto::hash, cryptonote::transaction>> transactions(amounts.size());
- threads = std::thread::hardware_concurrency();
- if (!m_db->can_thread_bulk_indices())
- threads = 1;
+ threads = std::thread::hardware_concurrency();
+ if (!m_db->can_thread_bulk_indices())
+ threads = 1;
- if (threads > 1)
- {
- boost::asio::io_service ioservice;
- boost::thread_group threadpool;
- std::unique_ptr < boost::asio::io_service::work > work(new boost::asio::io_service::work(ioservice));
-
- for (uint64_t i = 0; i < threads; i++)
- {
- threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
- }
+ if (threads > 1)
+ {
+ boost::asio::io_service ioservice;
+ boost::thread_group threadpool;
+ std::unique_ptr < boost::asio::io_service::work > work(new boost::asio::io_service::work(ioservice));
- for (size_t i = 0; i < amounts.size(); i++)
- {
- uint64_t amount = amounts[i];
- ioservice.dispatch(boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount]), std::ref(transactions[i])));
- }
+ for (uint64_t i = 0; i < threads; i++)
+ {
+ threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
+ }
- work.reset();
- threadpool.join_all();
- ioservice.stop();
+ for (size_t i = 0; i < amounts.size(); i++)
+ {
+ uint64_t amount = amounts[i];
+ ioservice.dispatch(boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount]), std::ref(transactions[i])));
}
- else
+
+ work.reset();
+ threadpool.join_all();
+ ioservice.stop();
+ }
+ else
+ {
+ for (size_t i = 0; i < amounts.size(); i++)
{
- for (size_t i = 0; i < amounts.size(); i++)
- {
- uint64_t amount = amounts[i];
- output_scan_worker(amount, offset_map[amount], tx_map[amount], transactions[i]);
- }
+ uint64_t amount = amounts[i];
+ output_scan_worker(amount, offset_map[amount], tx_map[amount], transactions[i]);
}
+ }
- int total_txs = 0;
+ int total_txs = 0;
- // now generate a table for each tx_prefix and k_image hashes
- for (const auto &entry : blocks_entry)
+ // now generate a table for each tx_prefix and k_image hashes
+ for (const auto &entry : blocks_entry)
+ {
+ for (const auto &tx_blob : entry.txs)
{
- for (const auto &tx_blob : entry.txs)
- {
- crypto::hash tx_hash = null_hash;
- crypto::hash tx_prefix_hash = null_hash;
- transaction tx;
+ crypto::hash tx_hash = null_hash;
+ crypto::hash tx_prefix_hash = null_hash;
+ transaction tx;
+
+ if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash))
+ SCAN_TABLE_QUIT("Could not parse tx from incoming blocks.");
- if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash))
- SCAN_TABLE_QUIT("Could not parse tx from incoming blocks.");
+ ++total_txs;
+ auto its = m_scan_table.find(tx_prefix_hash);
+ if (its == m_scan_table.end())
+ SCAN_TABLE_QUIT("Tx not found on scan table from incoming blocks.");
- ++total_txs;
- auto its = m_scan_table.find(tx_prefix_hash);
- if (its == m_scan_table.end())
- SCAN_TABLE_QUIT("Tx not found on scan table from incoming blocks.");
+ for (const auto &txin : tx.vin)
+ {
+ const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
+ auto needed_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
+
+ std::vector<output_data_t> outputs;
+ for (const uint64_t & offset_needed : needed_offsets)
+ {
+ size_t pos = 0;
+ bool found = false;
- for (const auto &txin : tx.vin)
+ for (const uint64_t &offset_found : offset_map[in_to_key.amount])
+ {
+ if (offset_needed == offset_found)
{
- const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
- auto needed_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
-
- std::vector<output_data_t> outputs;
- for (const uint64_t & offset_needed : needed_offsets)
- {
- size_t pos = 0;
- bool found = false;
-
- for (const uint64_t &offset_found : offset_map[in_to_key.amount])
- {
- if (offset_needed == offset_found)
- {
- found = true;
- break;
- }
-
- ++pos;
- }
-
- if (found && pos < tx_map[in_to_key.amount].size())
- outputs.push_back(tx_map[in_to_key.amount].at(pos));
- else
- break;
- }
-
- its->second.emplace(in_to_key.k_image, outputs);
+ found = true;
+ break;
}
+
+ ++pos;
+ }
+
+ if (found && pos < tx_map[in_to_key.amount].size())
+ outputs.push_back(tx_map[in_to_key.amount].at(pos));
+ else
+ break;
}
- }
- TIME_MEASURE_FINISH(scantable);
- if (total_txs > 0)
- {
- m_fake_scan_time = scantable / total_txs;
- if(m_show_time_stats)
- LOG_PRINT_L0("Prepare scantable took: " << scantable << " ms");
+ its->second.emplace(in_to_key.k_image, outputs);
+ }
}
+ }
- return true;
+ TIME_MEASURE_FINISH(scantable);
+ if (total_txs > 0)
+ {
+ m_fake_scan_time = scantable / total_txs;
+ if(m_show_time_stats)
+ LOG_PRINT_L0("Prepare scantable took: " << scantable << " ms");
+ }
+
+ return true;
}
void Blockchain::set_user_options(uint64_t maxthreads, uint64_t blocks_per_sync, blockchain_db_sync_mode sync_mode, bool fast_sync)
{
- m_db_sync_mode = sync_mode;
- m_fast_sync = fast_sync;
- m_db_blocks_per_sync = blocks_per_sync;
- m_max_prepare_blocks_threads = maxthreads;
+ m_db_sync_mode = sync_mode;
+ m_fast_sync = fast_sync;
+ m_db_blocks_per_sync = blocks_per_sync;
+ m_max_prepare_blocks_threads = maxthreads;
}
HardFork::State Blockchain::get_hard_fork_state() const
{
- return m_hardfork->get_state();
+ return m_hardfork->get_state();
}
bool Blockchain::get_hard_fork_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint8_t &voting) const
{
- return m_hardfork->get_voting_info(version, window, votes, threshold, voting);
+ return m_hardfork->get_voting_info(version, window, votes, threshold, voting);
}
bool Blockchain::for_all_key_images(std::function<bool(const crypto::key_image&)> f) const
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index f0b03ab0a..e8f5a7e5b 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
@@ -61,11 +61,11 @@ namespace cryptonote
enum blockchain_db_sync_mode
{
- db_sync,
- db_async,
- db_nosync
+ db_sync,
+ db_async,
+ db_nosync
};
-
+
/************************************************************************/
/* */
/************************************************************************/
@@ -153,10 +153,10 @@ namespace cryptonote
// user options, must be called before calling init()
void set_user_options(uint64_t block_threads, uint64_t blocks_per_sync,
- blockchain_db_sync_mode sync_mode, bool fast_sync);
+ blockchain_db_sync_mode sync_mode, bool fast_sync);
void set_show_time_stats(bool stats) { m_show_time_stats = stats; }
-
+
HardFork::State get_hard_fork_state() const;
uint8_t get_current_hard_fork_version() const { return m_hardfork->get_current_version(); }
uint8_t get_ideal_hard_fork_version() const { return m_hardfork->get_ideal_version(); }
@@ -174,12 +174,12 @@ namespace cryptonote
return *m_db;
}
- void output_scan_worker(const uint64_t amount,const std::vector<uint64_t> &offsets,
- std::vector<output_data_t> &outputs, std::unordered_map<crypto::hash,
- cryptonote::transaction> &txs) const;
+ void output_scan_worker(const uint64_t amount,const std::vector<uint64_t> &offsets,
+ std::vector<output_data_t> &outputs, std::unordered_map<crypto::hash,
+ cryptonote::transaction> &txs) const;
- void block_longhash_worker(const uint64_t height, const std::vector<block> &blocks,
- std::unordered_map<crypto::hash, crypto::hash> &map) const;
+ void block_longhash_worker(const uint64_t height, const std::vector<block> &blocks,
+ std::unordered_map<crypto::hash, crypto::hash> &map) const;
private:
typedef std::unordered_map<crypto::hash, size_t> blocks_by_id_index;
typedef std::unordered_map<crypto::hash, transaction_chain_entry> transactions_container;
@@ -208,22 +208,22 @@ namespace cryptonote
// SHA-3 hashes for each block and for fast pow checking
std::vector<crypto::hash> m_blocks_hash_check;
std::vector<crypto::hash> m_blocks_txs_check;
-
- blockchain_db_sync_mode m_db_sync_mode;
- bool m_fast_sync;
- bool m_show_time_stats;
- uint64_t m_db_blocks_per_sync;
- uint64_t m_max_prepare_blocks_threads;
+
+ blockchain_db_sync_mode m_db_sync_mode;
+ bool m_fast_sync;
+ bool m_show_time_stats;
+ uint64_t m_db_blocks_per_sync;
+ uint64_t m_max_prepare_blocks_threads;
uint64_t m_fake_pow_calc_time;
uint64_t m_fake_scan_time;
- uint64_t m_sync_counter;
- std::vector<uint64_t> m_timestamps;
- std::vector<difficulty_type> m_difficulties;
- uint64_t m_timestamps_and_difficulties_height;
+ uint64_t m_sync_counter;
+ std::vector<uint64_t> m_timestamps;
+ std::vector<difficulty_type> m_difficulties;
+ uint64_t m_timestamps_and_difficulties_height;
- boost::asio::io_service m_async_service;
- boost::thread_group m_async_pool;
- std::unique_ptr<boost::asio::io_service::work> m_async_work_idle;
+ boost::asio::io_service m_async_service;
+ boost::thread_group m_async_pool;
+ std::unique_ptr<boost::asio::io_service::work> m_async_work_idle;
// all alternative chains
blocks_ext_by_hash m_alternative_chains; // crypto::hash -> block_extended_info
@@ -273,6 +273,6 @@ namespace cryptonote
bool check_for_double_spend(const transaction& tx, key_images_container& keys_this_block) const;
void get_timestamp_and_difficulty(uint64_t &timestamp, difficulty_type &difficulty, const int offset) const;
void check_ring_signature(const crypto::hash &tx_prefix_hash, const crypto::key_image &key_image,
- const std::vector<crypto::public_key> &pubkeys, const std::vector<crypto::signature> &sig, uint64_t &result);
+ const std::vector<crypto::public_key> &pubkeys, const std::vector<crypto::signature> &sig, uint64_t &result);
};
} // namespace cryptonote
diff --git a/src/cryptonote_core/blockchain_storage.cpp b/src/cryptonote_core/blockchain_storage.cpp
index 72bd05f6a..ee8fac368 100644
--- a/src/cryptonote_core/blockchain_storage.cpp
+++ b/src/cryptonote_core/blockchain_storage.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <algorithm>
@@ -97,11 +97,11 @@ bool blockchain_storage::init(const std::string& config_folder, bool testnet)
{
// checkpoints
-
+
// mainchain
- for (size_t height=0; height < m_blocks.size(); ++height)
+ for (size_t height=0; height < m_blocks.size(); ++height)
{
- CHECK_AND_ASSERT_MES((!m_checkpoints.is_in_checkpoint_zone(height)) || m_checkpoints.check_block(height,get_block_hash(m_blocks[height].bl)),false,"checkpoint fail, blockchain.bin invalid");
+ CHECK_AND_ASSERT_MES((!m_checkpoints.is_in_checkpoint_zone(height)) || m_checkpoints.check_block(height,get_block_hash(m_blocks[height].bl)),false,"checkpoint fail, blockchain.bin invalid");
}
// check alt chains
@@ -110,7 +110,7 @@ bool blockchain_storage::init(const std::string& config_folder, bool testnet)
// see issue #118
BOOST_FOREACH(blocks_ext_by_hash::value_type& alt_block, m_alternative_chains)
{
- CHECK_AND_ASSERT_MES(m_checkpoints.is_alternative_block_allowed(m_blocks.size()-1,alt_block.second.height),false,"stored alternative block not allowed, blockchain.bin invalid");
+ CHECK_AND_ASSERT_MES(m_checkpoints.is_alternative_block_allowed(m_blocks.size()-1,alt_block.second.height),false,"stored alternative block not allowed, blockchain.bin invalid");
}
#endif
}
@@ -661,7 +661,7 @@ bool blockchain_storage::create_block_template(block& b, const account_public_ad
b.timestamp = time(NULL);
height = m_blocks.size();
diffic = get_difficulty_for_next_block();
- CHECK_AND_ASSERT_MES(diffic, false, "difficulty owverhead.");
+ CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead.");
median_size = m_current_block_cumul_sz_limit / 2;
already_generated_coins = m_blocks.back().already_generated_coins;
@@ -1072,13 +1072,13 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO
size_t try_count = 0;
for(uint64_t j = 0; j != req.outs_count && try_count < up_index_limit;)
{
- // triangular distribution over [a,b) with a=0, mode c=b=up_index_limit
+ // triangular distribution over [a,b) with a=0, mode c=b=up_index_limit
uint64_t r = crypto::rand<uint64_t>() % ((uint64_t)1 << 53);
- double frac = std::sqrt((double)r / ((uint64_t)1 << 53));
- size_t i = (size_t)(frac*up_index_limit);
- // just in case rounding up to 1 occurs after sqrt
- if (i == up_index_limit)
- --i;
+ double frac = std::sqrt((double)r / ((uint64_t)1 << 53));
+ size_t i = (size_t)(frac*up_index_limit);
+ // just in case rounding up to 1 occurs after sqrt
+ if (i == up_index_limit)
+ --i;
if(used.count(i))
continue;
bool added = add_out_to_get_random_outs(amount_outs, result_outs, amount, i);
@@ -1155,27 +1155,27 @@ uint64_t blockchain_storage::block_difficulty(size_t i) const
//------------------------------------------------------------------
double blockchain_storage::get_avg_block_size( size_t count) const
{
- if (count > get_current_blockchain_height()) return 500;
+ if (count > get_current_blockchain_height()) return 500;
+
+ double average = 0;
+ _dbg1_c("net/blksize", "HEIGHT: " << get_current_blockchain_height());
+ _dbg1_c("net/blksize", "BLOCK ID BY HEIGHT: " << get_block_id_by_height(get_current_blockchain_height()) );
+ _dbg1_c("net/blksize", "BLOCK TAIL ID: " << get_tail_id() );
+ std::vector<size_t> size_vector;
- double average = 0;
- _dbg1_c("net/blksize", "HEIGHT: " << get_current_blockchain_height());
- _dbg1_c("net/blksize", "BLOCK ID BY HEIGHT: " << get_block_id_by_height(get_current_blockchain_height()) );
- _dbg1_c("net/blksize", "BLOCK TAIL ID: " << get_tail_id() );
- std::vector<size_t> size_vector;
+ get_backward_blocks_sizes(get_current_blockchain_height() - count, size_vector, count);
- get_backward_blocks_sizes(get_current_blockchain_height() - count, size_vector, count);
+ std::vector<size_t>::iterator it;
+ it = size_vector.begin();
+ while (it != size_vector.end()) {
+ average += *it;
+ _dbg2_c("net/blksize", "VECTOR ELEMENT: " << (*it) );
+ it++;
+ }
+ average = average / count;
+ _dbg1_c("net/blksize", "VECTOR SIZE: " << size_vector.size() << " average=" << average);
- std::vector<size_t>::iterator it;
- it = size_vector.begin();
- while (it != size_vector.end()) {
- average += *it;
- _dbg2_c("net/blksize", "VECTOR ELEMENT: " << (*it) );
- it++;
- }
- average = average / count;
- _dbg1_c("net/blksize", "VECTOR SIZE: " << size_vector.size() << " average=" << average);
-
- return average;
+ return average;
}
//------------------------------------------------------------------
void blockchain_storage::print_blockchain(uint64_t start_index, uint64_t end_index) const
@@ -1248,7 +1248,7 @@ bool blockchain_storage::find_blockchain_supplement(const uint64_t req_start_blo
{
CRITICAL_REGION_LOCAL(m_blockchain_lock);
if(req_start_block > 0) {
- start_height = req_start_block;
+ start_height = req_start_block;
} else {
if(!find_blockchain_supplement(qblock_ids, start_height))
return false;
@@ -1739,9 +1739,9 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
bei.block_cumulative_size = cumulative_block_size;
bei.cumulative_difficulty = current_diffic;
- // In the "tail" state when the minimum subsidy (implemented in get_block_reward) is in effect, the number of
- // coins will eventually exceed MONEY_SUPPLY and overflow a uint64. To prevent overflow, cap already_generated_coins
- // at MONEY_SUPPLY. already_generated_coins is only used to compute the block subsidy and MONEY_SUPPLY yields a
+ // In the "tail" state when the minimum subsidy (implemented in get_block_reward) is in effect, the number of
+ // coins will eventually exceed MONEY_SUPPLY and overflow a uint64. To prevent overflow, cap already_generated_coins
+ // at MONEY_SUPPLY. already_generated_coins is only used to compute the block subsidy and MONEY_SUPPLY yields a
// subsidy of 0 under the base formula and therefore the minimum subsidy >0 in the tail state.
bei.already_generated_coins = base_reward < (MONEY_SUPPLY-already_generated_coins) ? already_generated_coins + base_reward : MONEY_SUPPLY;
@@ -1770,7 +1770,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
<< "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size
<< ", " << block_processing_time << "("<< target_calculating_time << "/" << longhash_calculating_time << ")ms");
- epee::net_utils::data_logger::get_instance().add_data("blockchain_processing_time", block_processing_time);
+ epee::net_utils::data_logger::get_instance().add_data("blockchain_processing_time", block_processing_time);
bvc.m_added_to_main_chain = true;
/*if(!m_orphanes_reorganize_in_work)
@@ -1837,13 +1837,13 @@ void blockchain_storage::check_against_checkpoints(const checkpoints& points, bo
// if asked to enforce checkpoints, roll back to a couple of blocks before the checkpoint
if (enforce)
{
- LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!");
- std::list<block> empty;
- rollback_blockchain_switching(empty, pt.first - 2);
+ LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!");
+ std::list<block> empty;
+ rollback_blockchain_switching(empty, pt.first - 2);
}
else
{
- LOG_ERROR("WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option");
+ LOG_ERROR("WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option");
}
}
}
diff --git a/src/cryptonote_core/checkpoints_create.cpp b/src/cryptonote_core/checkpoints_create.cpp
index de7d65009..2360c56de 100644
--- a/src/cryptonote_core/checkpoints_create.cpp
+++ b/src/cryptonote_core/checkpoints_create.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "checkpoints_create.h"
@@ -46,11 +46,11 @@ namespace
bool ok = false;
for (const auto& record_in_b : b)
{
- if (record_in_a == record_in_b)
- {
- ok = true;
- break;
- }
+ if (record_in_a == record_in_b)
+ {
+ ok = true;
+ break;
+ }
}
if (!ok) return false;
}
@@ -62,25 +62,25 @@ namespace
namespace cryptonote
{
-struct t_hashline
+struct t_hashline
{
- uint64_t height;
- std::string hash;
- BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(height)
- KV_SERIALIZE(hash)
- END_KV_SERIALIZE_MAP()
+ uint64_t height;
+ std::string hash;
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(height)
+ KV_SERIALIZE(hash)
+ END_KV_SERIALIZE_MAP()
};
struct t_hash_json {
- std::vector<t_hashline> hashlines;
- BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(hashlines)
- END_KV_SERIALIZE_MAP()
+ std::vector<t_hashline> hashlines;
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(hashlines)
+ END_KV_SERIALIZE_MAP()
};
bool create_checkpoints(cryptonote::checkpoints& checkpoints)
-{
+{
ADD_CHECKPOINT(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148");
ADD_CHECKPOINT(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381");
ADD_CHECKPOINT(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d");
@@ -126,11 +126,11 @@ bool load_checkpoints_from_json(cryptonote::checkpoints& checkpoints, std::strin
uint64_t height;
height = it->height;
if (height <= prev_max_height) {
- LOG_PRINT_L1("ignoring checkpoint height " << height);
+ LOG_PRINT_L1("ignoring checkpoint height " << height);
} else {
- std::string blockhash = it->hash;
- LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash);
- ADD_CHECKPOINT(height, blockhash);
+ std::string blockhash = it->hash;
+ LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash);
+ ADD_CHECKPOINT(height, blockhash);
}
++it;
}
@@ -142,15 +142,15 @@ bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testne
{
// All four MoneroPulse domains have DNSSEC on and valid
static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
- , "checkpoints.moneropulse.org"
- , "checkpoints.moneropulse.net"
- , "checkpoints.moneropulse.co"
+ , "checkpoints.moneropulse.org"
+ , "checkpoints.moneropulse.net"
+ , "checkpoints.moneropulse.co"
};
static const std::vector<std::string> testnet_dns_urls = { "testpoints.moneropulse.se"
- , "testpoints.moneropulse.org"
- , "testpoints.moneropulse.net"
- , "testpoints.moneropulse.co"
+ , "testpoints.moneropulse.org"
+ , "testpoints.moneropulse.net"
+ , "testpoints.moneropulse.co"
};
std::vector<std::vector<std::string> > records;
@@ -220,8 +220,8 @@ bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testne
{
if (dns_records_match(records[i], records[j]))
{
- good_records_index = i;
- break;
+ good_records_index = i;
+ break;
}
}
if (good_records_index >= 0) break;
@@ -246,7 +246,7 @@ bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testne
std::stringstream ss(record.substr(0, pos));
if (!(ss >> height))
{
- continue;
+ continue;
}
// parse the second part as crypto::hash,
@@ -254,7 +254,7 @@ bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testne
std::string hashStr = record.substr(pos + 1);
if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash))
{
- continue;
+ continue;
}
ADD_CHECKPOINT(height, hashStr);
diff --git a/src/cryptonote_core/cryptonote_basic_impl.cpp b/src/cryptonote_core/cryptonote_basic_impl.cpp
index 73e8d8fb9..9ced19890 100644
--- a/src/cryptonote_core/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_core/cryptonote_basic_impl.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "include_base_utils.h"
@@ -106,8 +106,8 @@ namespace cryptonote {
assert(current_block_size < std::numeric_limits<uint32_t>::max());
uint64_t product_hi;
- // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being
- // treated as 32-bit by default.
+ // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being
+ // treated as 32-bit by default.
uint64_t multiplicand = 2 * median_size - current_block_size;
multiplicand *= current_block_size;
uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi);
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 960c8eff8..8a3b81205 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "include_base_utils.h"
@@ -63,7 +63,7 @@ namespace cryptonote
m_blockchain_storage(&m_mempool),
#endif
m_miner(this),
- m_miner_address(boost::value_initialized<account_public_address>()),
+ m_miner_address(boost::value_initialized<account_public_address>()),
m_starter_message_showed(false),
m_target_blockchain_height(0),
m_checkpoints_path(""),
@@ -176,10 +176,10 @@ namespace cryptonote
set_enforce_dns_checkpoints(command_line::get_arg(vm, command_line::arg_dns_checkpoints));
test_drop_download_height(command_line::get_arg(vm, command_line::arg_test_drop_download_height));
-
+
if (command_line::get_arg(vm, command_line::arg_test_drop_download) == true)
- test_drop_download();
-
+ test_drop_download();
+
return true;
}
//-----------------------------------------------------------------------------------------------
@@ -331,7 +331,7 @@ namespace cryptonote
db->set_auto_remove_logs(auto_remove_logs);
db->open(filename, db_flags);
if(!db->m_open)
- return false;
+ return false;
}
catch (const DB_ERROR& e)
{
@@ -374,12 +374,12 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::deinit()
{
- m_miner.stop();
- m_mempool.deinit();
- if (!m_fast_exit)
- {
- m_blockchain_storage.deinit();
- }
+ m_miner.stop();
+ m_mempool.deinit();
+ if (!m_fast_exit)
+ {
+ m_blockchain_storage.deinit();
+ }
return true;
}
//-----------------------------------------------------------------------------------------------
@@ -395,28 +395,28 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
void core::test_drop_download()
{
- m_test_drop_download = false;
+ m_test_drop_download = false;
}
//-----------------------------------------------------------------------------------------------
void core::test_drop_download_height(uint64_t height)
{
- m_test_drop_download_height = height;
+ m_test_drop_download_height = height;
}
//-----------------------------------------------------------------------------------------------
bool core::get_test_drop_download() const
{
- return m_test_drop_download;
+ return m_test_drop_download;
}
//-----------------------------------------------------------------------------------------------
bool core::get_test_drop_download_height() const
{
- if (m_test_drop_download_height == 0)
- return true;
-
- if (get_blockchain_storage().get_current_blockchain_height() <= m_test_drop_download_height)
- return true;
+ if (m_test_drop_download_height == 0)
+ return true;
+
+ if (get_blockchain_storage().get_current_blockchain_height() <= m_test_drop_download_height)
+ return true;
- return false;
+ return false;
}
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed)
@@ -852,14 +852,14 @@ namespace cryptonote
{
if(!m_starter_message_showed)
{
- LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL
- << "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL
+ LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL
+ << "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL
<< ENDL
<< "You can set the level of process detailization* through \"set_log <level>\" command*, where <level> is between 0 (no details) and 4 (very verbose)." << ENDL
<< ENDL
<< "Use \"help\" command to see the list of available commands." << ENDL
<< ENDL
- << "Note: in case you need to interrupt the process, use \"exit\" command. Otherwise, the current progress won't be saved." << ENDL
+ << "Note: in case you need to interrupt the process, use \"exit\" command. Otherwise, the current progress won't be saved." << ENDL
<< "**********************************************************************");
m_starter_message_showed = true;
}
@@ -915,6 +915,6 @@ namespace cryptonote
{
raise(SIGTERM);
}
-
+
std::atomic<bool> core::m_fast_exit(false);
}
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 5d665cb98..e91d28694 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
@@ -68,7 +68,7 @@ namespace cryptonote
bool handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate = true);
bool prepare_handle_incoming_blocks(const std::list<block_complete_entry> &blocks);
bool cleanup_handle_incoming_blocks(bool force_sync = false);
-
+
bool check_incoming_block_size(const blobdata& block_blob) const;
i_cryptonote_protocol* get_protocol(){return m_pprotocol;}
@@ -175,7 +175,7 @@ namespace cryptonote
static std::atomic<bool> m_fast_exit;
bool m_test_drop_download = true;
- uint64_t m_test_drop_download_height = 0;
+ uint64_t m_test_drop_download_height = 0;
tx_memory_pool m_mempool;
#if BLOCKCHAIN_DB == DB_LMDB
diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp
index 3c3f1dec1..9a4f5d080 100644
--- a/src/cryptonote_core/difficulty.cpp
+++ b/src/cryptonote_core/difficulty.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <algorithm>
@@ -53,40 +53,40 @@ namespace cryptonote {
#else
static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) {
- // __int128 isn't part of the standard, so the previous function wasn't portable. mul128() in Windows is fine,
- // but this portable function should be used elsewhere. Credit for this function goes to latexi95.
-
- uint64_t aLow = a & 0xFFFFFFFF;
- uint64_t aHigh = a >> 32;
- uint64_t bLow = b & 0xFFFFFFFF;
- uint64_t bHigh = b >> 32;
-
- uint64_t res = aLow * bLow;
- uint64_t lowRes1 = res & 0xFFFFFFFF;
- uint64_t carry = res >> 32;
-
- res = aHigh * bLow + carry;
- uint64_t highResHigh1 = res >> 32;
- uint64_t highResLow1 = res & 0xFFFFFFFF;
-
- res = aLow * bHigh;
- uint64_t lowRes2 = res & 0xFFFFFFFF;
- carry = res >> 32;
-
- res = aHigh * bHigh + carry;
- uint64_t highResHigh2 = res >> 32;
- uint64_t highResLow2 = res & 0xFFFFFFFF;
-
- //Addition
-
- uint64_t r = highResLow1 + lowRes2;
- carry = r >> 32;
- low = (r << 32) | lowRes1;
- r = highResHigh1 + highResLow2 + carry;
- uint64_t d3 = r & 0xFFFFFFFF;
- carry = r >> 32;
- r = highResHigh2 + carry;
- high = d3 | (r << 32);
+ // __int128 isn't part of the standard, so the previous function wasn't portable. mul128() in Windows is fine,
+ // but this portable function should be used elsewhere. Credit for this function goes to latexi95.
+
+ uint64_t aLow = a & 0xFFFFFFFF;
+ uint64_t aHigh = a >> 32;
+ uint64_t bLow = b & 0xFFFFFFFF;
+ uint64_t bHigh = b >> 32;
+
+ uint64_t res = aLow * bLow;
+ uint64_t lowRes1 = res & 0xFFFFFFFF;
+ uint64_t carry = res >> 32;
+
+ res = aHigh * bLow + carry;
+ uint64_t highResHigh1 = res >> 32;
+ uint64_t highResLow1 = res & 0xFFFFFFFF;
+
+ res = aLow * bHigh;
+ uint64_t lowRes2 = res & 0xFFFFFFFF;
+ carry = res >> 32;
+
+ res = aHigh * bHigh + carry;
+ uint64_t highResHigh2 = res >> 32;
+ uint64_t highResLow2 = res & 0xFFFFFFFF;
+
+ //Addition
+
+ uint64_t r = highResLow1 + lowRes2;
+ carry = r >> 32;
+ low = (r << 32) | lowRes1;
+ r = highResHigh1 + highResLow2 + carry;
+ uint64_t d3 = r & 0xFFFFFFFF;
+ carry = r >> 32;
+ r = highResHigh2 + carry;
+ high = d3 | (r << 32);
}
#endif
diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp
index b99113d9e..abb74b740 100644
--- a/src/cryptonote_core/miner.cpp
+++ b/src/cryptonote_core/miner.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <sstream>
@@ -68,9 +68,9 @@ namespace cryptonote
m_thread_index(0),
m_phandler(phandler),
m_height(0),
- m_pausers_count(0),
+ m_pausers_count(0),
m_threads_total(0),
- m_starter_nonce(0),
+ m_starter_nonce(0),
m_last_hr_merge_time(0),
m_hashes(0),
m_do_print_hashrate(false),
@@ -109,7 +109,7 @@ namespace cryptonote
block bl = AUTO_VAL_INIT(bl);
difficulty_type di = AUTO_VAL_INIT(di);
uint64_t height = AUTO_VAL_INIT(height);
- cryptonote::blobdata extra_nonce;
+ cryptonote::blobdata extra_nonce;
if(m_extra_messages.size() && m_config.current_extra_message_index < m_extra_messages.size())
{
extra_nonce = m_extra_messages[m_config.current_extra_message_index];
@@ -135,7 +135,7 @@ namespace cryptonote
merge_hr();
return true;
});
-
+
return true;
}
//-----------------------------------------------------------------------------------------------------
@@ -227,7 +227,7 @@ namespace cryptonote
uint32_t miner::get_threads_count() const {
return m_threads_total;
}
- //-----------------------------------------------------------------------------------------------------
+ //-----------------------------------------------------------------------------------------------------
bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs)
{
m_mine_address = adr;
@@ -346,7 +346,7 @@ namespace cryptonote
difficulty_type local_diff = 0;
uint32_t local_template_ver = 0;
block b;
- slow_hash_allocate_state();
+ slow_hash_allocate_state();
while(!m_stop)
{
if(m_pausers_count)//anti split workaround
@@ -357,7 +357,6 @@ namespace cryptonote
if(local_template_ver != m_template_no)
{
-
CRITICAL_REGION_BEGIN(m_template_lock);
b = m_template;
local_diff = m_diffic;
@@ -395,7 +394,7 @@ namespace cryptonote
nonce+=m_threads_total;
++m_hashes;
}
- slow_hash_free_state();
+ slow_hash_free_state();
LOG_PRINT_L0("Miner thread stopped ["<< th_local_index << "]");
return true;
}
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index e2dcd35f5..5ee6c38cc 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <algorithm>
@@ -228,8 +228,8 @@ namespace cryptonote
bool tx_memory_pool::remove_transaction_keyimages(const transaction& tx)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
- // ND: Speedup
- // 1. Move transaction hash calcuation outside of loop. ._.
+ // ND: Speedup
+ // 1. Move transaction hash calcuation outside of loop. ._.
crypto::hash actual_hash = get_transaction_hash(tx);
BOOST_FOREACH(const txin_v& vi, tx.vin)
{
@@ -299,7 +299,7 @@ namespace cryptonote
{
uint64_t tx_age = time(nullptr) - it->second.receive_time;
- if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !it->second.kept_by_block) ||
+ if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !it->second.kept_by_block) ||
(tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && it->second.kept_by_block) )
{
LOG_PRINT_L1("Tx " << it->first << " removed from tx pool due to outdated, age: " << tx_age );
@@ -574,7 +574,7 @@ namespace cryptonote
// If adding this tx will make the block size
// greater than CRYPTONOTE_GETBLOCKTEMPLATE_MAX
- // _BLOCK_SIZE bytes, reject the tx; this will
+ // _BLOCK_SIZE bytes, reject the tx; this will
// keep block sizes from becoming too unwieldly
// to propagate at 60s block times.
if ( (total_size + tx_it->second.blob_size) > CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE )
@@ -586,7 +586,7 @@ namespace cryptonote
// If we've exceeded the penalty free size,
// stop including more tx
if (total_size > median_size)
- break;
+ break;
// Skip transactions that are not ready to be
// included into the blockchain or that are
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index a72c331a7..4dcca579c 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
@@ -139,7 +139,7 @@ namespace cryptonote
};
private:
- bool remove_stuck_transactions();
+ bool remove_stuck_transactions();
bool have_tx_keyimg_as_spent(const crypto::key_image& key_im) const;
bool have_tx_keyimges_as_spent(const transaction& tx) const;
bool remove_transaction_keyimages(const transaction& tx);
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 9099cd414..38b1e7321 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -3,23 +3,23 @@
/// @brief This is the orginal cryptonote protocol network-events handler, modified by us
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -29,7 +29,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
// (may contain code and/or modifications by other developers)
@@ -49,14 +49,14 @@ namespace cryptonote
{
-// static
-// template<class t_core> std::ofstream t_cryptonote_protocol_handler<t_core>::m_logreq("logreq.txt"); // static
+// static
+// template<class t_core> std::ofstream t_cryptonote_protocol_handler<t_core>::m_logreq("logreq.txt"); // static
- //-----------------------------------------------------------------------------------------------------------------------
+ //-----------------------------------------------------------------------------------------------------------------------
template<class t_core>
- t_cryptonote_protocol_handler<t_core>::t_cryptonote_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint<connection_context>* p_net_layout):m_core(rcore),
+ t_cryptonote_protocol_handler<t_core>::t_cryptonote_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint<connection_context>* p_net_layout):m_core(rcore),
m_p2p(p_net_layout),
m_syncronized_connections_count(0),
m_synchronized(false)
@@ -66,21 +66,21 @@ namespace cryptonote
m_p2p = &m_p2p_stub;
}
//-----------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::init(const boost::program_options::variables_map& vm)
{
return true;
}
- //------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::deinit()
{
-
+
return true;
}
- //------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
void t_cryptonote_protocol_handler<t_core>::set_p2p_endpoint(nodetool::i_p2p_endpoint<connection_context>* p2p)
{
if(p2p)
@@ -88,8 +88,8 @@ namespace cryptonote
else
m_p2p = &m_p2p_stub;
}
- //------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::on_callback(cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("callback fired");
@@ -107,22 +107,22 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::get_stat_info(core_stat_info& stat_inf)
{
return m_core.get_stat_info(stat_inf);
}
- //------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
void t_cryptonote_protocol_handler<t_core>::log_connections()
{
std::stringstream ss;
ss.precision(1);
-
- double down_sum = 0.0;
- double down_curr_sum = 0.0;
- double up_sum = 0.0;
- double up_curr_sum = 0.0;
+
+ double down_sum = 0.0;
+ double down_curr_sum = 0.0;
+ double up_sum = 0.0;
+ double up_curr_sum = 0.0;
ss << std::setw(30) << std::left << "Remote Host"
<< std::setw(20) << "Peer id"
@@ -131,19 +131,19 @@ namespace cryptonote
<< std::setw(20) << "Livetime(sec)"
<< std::setw(12) << "Down (kB/s)"
<< std::setw(14) << "Down(now)"
- << std::setw(10) << "Up (kB/s)"
+ << std::setw(10) << "Up (kB/s)"
<< std::setw(13) << "Up(now)"
<< ENDL;
- uint32_t ip;
+ uint32_t ip;
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id)
{
- bool local_ip = false;
- ip = ntohl(cntxt.m_remote_ip);
- // TODO: local ip in calss A, B
- if (ip > 3232235520 && ip < 3232301055) // 192.168.x.x
- local_ip = true;
- auto connection_time = time(NULL) - cntxt.m_started;
+ bool local_ip = false;
+ ip = ntohl(cntxt.m_remote_ip);
+ // TODO: local ip in calss A, B
+ if (ip > 3232235520 && ip < 3232301055) // 192.168.x.x
+ local_ip = true;
+ auto connection_time = time(NULL) - cntxt.m_started;
ss << std::setw(30) << std::left << std::string(cntxt.m_is_income ? " [INC]":"[OUT]") +
epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
<< std::setw(20) << std::hex << peer_id
@@ -157,30 +157,30 @@ namespace cryptonote
<< (local_ip ? "[LAN]" : "")
<< std::left << (ip == LOCALHOST_INT ? "[LOCALHOST]" : "") // 127.0.0.1
<< ENDL;
-
- if (connection_time > 1)
- {
- down_sum += (cntxt.m_recv_cnt / connection_time / 1024);
- up_sum += (cntxt.m_send_cnt / connection_time / 1024);
- }
-
- down_curr_sum += (cntxt.m_current_speed_down / 1024);
- up_curr_sum += (cntxt.m_current_speed_up / 1024);
-
+
+ if (connection_time > 1)
+ {
+ down_sum += (cntxt.m_recv_cnt / connection_time / 1024);
+ up_sum += (cntxt.m_send_cnt / connection_time / 1024);
+ }
+
+ down_curr_sum += (cntxt.m_current_speed_down / 1024);
+ up_curr_sum += (cntxt.m_current_speed_up / 1024);
+
return true;
});
- ss << ENDL
- << std::setw(125) << " "
- << std::setw(12) << down_sum
- << std::setw(14) << down_curr_sum
- << std::setw(10) << up_sum
- << std::setw(13) << up_curr_sum
- << ENDL;
- LOG_PRINT_L0("Connections: " << ENDL << ss.str());
+ ss << ENDL
+ << std::setw(125) << " "
+ << std::setw(12) << down_sum
+ << std::setw(14) << down_curr_sum
+ << std::setw(10) << up_sum
+ << std::setw(13) << up_curr_sum
+ << ENDL;
+ LOG_PRINT_L0("Connections: " << ENDL << ss.str());
}
- //------------------------------------------------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------------
// Returns a list of connection_info objects describing each open p2p connection
- //------------------------------------------------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------------------------------------------------
template<class t_core>
std::list<connection_info> t_cryptonote_protocol_handler<t_core>::get_connections()
{
@@ -209,43 +209,43 @@ namespace cryptonote
cnx.state = get_protocol_state_string(cntxt.m_state);
cnx.live_time = timestamp - cntxt.m_started;
-
+
uint32_t ip;
- ip = ntohl(cntxt.m_remote_ip);
- if (ip == LOCALHOST_INT)
- {
- cnx.localhost = true;
- }
- else
- {
- cnx.localhost = false;
- }
-
+ ip = ntohl(cntxt.m_remote_ip);
+ if (ip == LOCALHOST_INT)
+ {
+ cnx.localhost = true;
+ }
+ else
+ {
+ cnx.localhost = false;
+ }
+
if (ip > 3232235520 && ip < 3232301055) // 192.168.x.x
{
- cnx.local_ip = true;
- }
- else
- {
- cnx.local_ip = false;
- }
-
- auto connection_time = time(NULL) - cntxt.m_started;
- if (connection_time == 0)
- {
- cnx.avg_download = 0;
- cnx.avg_upload = 0;
- }
-
- else
- {
- cnx.avg_download = cntxt.m_recv_cnt / connection_time / 1024;
- cnx.avg_upload = cntxt.m_send_cnt / connection_time / 1024;
- }
-
- cnx.current_download = cntxt.m_current_speed_down / 1024;
- cnx.current_upload = cntxt.m_current_speed_up / 1024;
-
+ cnx.local_ip = true;
+ }
+ else
+ {
+ cnx.local_ip = false;
+ }
+
+ auto connection_time = time(NULL) - cntxt.m_started;
+ if (connection_time == 0)
+ {
+ cnx.avg_download = 0;
+ cnx.avg_upload = 0;
+ }
+
+ else
+ {
+ cnx.avg_download = cntxt.m_recv_cnt / connection_time / 1024;
+ cnx.avg_upload = cntxt.m_send_cnt / connection_time / 1024;
+ }
+
+ cnx.current_download = cntxt.m_current_speed_down / 1024;
+ cnx.current_upload = cntxt.m_current_speed_up / 1024;
+
connections.push_back(cnx);
return true;
@@ -254,7 +254,7 @@ namespace cryptonote
return connections;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::process_payload_sync_data(const CORE_SYNC_DATA& hshd, cryptonote_connection_context& context, bool is_inital)
{
if(context.m_state == cryptonote_connection_context::state_befor_handshake && !is_inital)
@@ -263,7 +263,7 @@ namespace cryptonote
if(context.m_state == cryptonote_connection_context::state_synchronizing)
return true;
- if(m_core.have_block(hshd.top_id))
+ if(m_core.have_block(hshd.top_id))
{
context.m_state = cryptonote_connection_context::state_normal;
if(is_inital)
@@ -271,11 +271,11 @@ namespace cryptonote
return true;
}
- /* As I don't know if accessing hshd from core could be a good practice,
+ /* As I don't know if accessing hshd from core could be a good practice,
I prefer pushing target height to the core at the same time it is pushed to the user.
Nz. */
m_core.set_target_blockchain_height(static_cast<int64_t>(hshd.current_height));
-
+
int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height());
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
<< " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TARGET) << " days) "
@@ -290,16 +290,16 @@ namespace cryptonote
m_p2p->request_callback(context);
return true;
}
- //------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::get_payload_sync_data(CORE_SYNC_DATA& hshd)
{
m_core.get_blockchain_top(hshd.current_height, hshd.top_id);
hshd.current_height +=1;
return true;
}
- //------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::get_payload_sync_data(blobdata& data)
{
CORE_SYNC_DATA hsd = boost::value_initialized<CORE_SYNC_DATA>();
@@ -307,8 +307,8 @@ namespace cryptonote
epee::serialization::store_t_to_binary(hsd, data);
return true;
}
- //------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("NOTIFY_NEW_BLOCK (hop " << arg.hop << ")");
@@ -333,7 +333,7 @@ namespace cryptonote
}
block_verification_context bvc = boost::value_initialized<block_verification_context>();
- m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block
+ m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block
m_core.cleanup_handle_incoming_blocks(true);
m_core.resume_mine();
if(bvc.m_verifivation_failed)
@@ -355,11 +355,11 @@ namespace cryptonote
LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
}
-
+
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("NOTIFY_NEW_TRANSACTIONS");
@@ -391,7 +391,7 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("NOTIFY_REQUEST_GET_OBJECTS");
@@ -401,7 +401,7 @@ namespace cryptonote
LOG_ERROR_CCONTEXT("failed to handle request NOTIFY_REQUEST_GET_OBJECTS, dropping connection");
m_p2p->drop_connection(context);
}
- LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()=" << rsp.blocks.size() << ", txs.size()=" << rsp.txs.size()
+ LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()=" << rsp.blocks.size() << ", txs.size()=" << rsp.txs.size()
<< ", rsp.m_current_blockchain_height=" << rsp.current_blockchain_height << ", missed_ids.size()=" << rsp.missed_ids.size());
post_notify<NOTIFY_RESPONSE_GET_OBJECTS>(rsp, context);
//handler_response_blocks_now(sizeof(rsp)); // XXX
@@ -410,67 +410,67 @@ namespace cryptonote
}
//------------------------------------------------------------------------------------------------------------------------
-
+
template<class t_core>
double t_cryptonote_protocol_handler<t_core>::get_avg_block_size() {
- // return m_core.get_blockchain_storage().get_avg_block_size(count); // this does not count too well the actuall network-size of data we need to download
-
- CRITICAL_REGION_LOCAL(m_buffer_mutex);
- double avg = 0;
- if (m_avg_buffer.size() == 0) {
- _warn("m_avg_buffer.size() == 0");
- return 500;
- }
-
- const bool dbg_poke_lock = 0; // debug: try to trigger an error by poking around with locks. TODO: configure option
- long int dbg_repeat=0;
- do {
- for (auto element : m_avg_buffer) avg += element;
- } while(dbg_poke_lock && (dbg_repeat++)<100000); // in debug/poke mode, repeat this calculation to trigger hidden locking error if there is one
- return avg / m_avg_buffer.size();
+ // return m_core.get_blockchain_storage().get_avg_block_size(count); // this does not count too well the actuall network-size of data we need to download
+
+ CRITICAL_REGION_LOCAL(m_buffer_mutex);
+ double avg = 0;
+ if (m_avg_buffer.size() == 0) {
+ _warn("m_avg_buffer.size() == 0");
+ return 500;
+ }
+
+ const bool dbg_poke_lock = 0; // debug: try to trigger an error by poking around with locks. TODO: configure option
+ long int dbg_repeat=0;
+ do {
+ for (auto element : m_avg_buffer) avg += element;
+ } while(dbg_poke_lock && (dbg_repeat++)<100000); // in debug/poke mode, repeat this calculation to trigger hidden locking error if there is one
+ return avg / m_avg_buffer.size();
}
-
+
template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("NOTIFY_RESPONSE_GET_OBJECTS");
-
+
// calculate size of request - mainly for logging/debug
size_t size = 0;
for (auto element : arg.txs) size += element.size();
-
- for (auto element : arg.blocks) {
- size += element.block.size();
- for (auto tx : element.txs)
- size += tx.size();
- }
-
- for (auto element : arg.missed_ids)
- size += sizeof(element.data);
-
- size += sizeof(arg.current_blockchain_height);
- {
- CRITICAL_REGION_LOCAL(m_buffer_mutex);
- m_avg_buffer.push_back(size);
-
- const bool dbg_poke_lock = 0; // debug: try to trigger an error by poking around with locks. TODO: configure option
- long int dbg_repeat=0;
- do {
- m_avg_buffer.push_back(666); // a test value
- m_avg_buffer.erase_end(1);
- } while(dbg_poke_lock && (dbg_repeat++)<100000); // in debug/poke mode, repeat this calculation to trigger hidden locking error if there is one
- }
- /*using namespace boost::chrono;
- auto point = steady_clock::now();
- auto time_from_epoh = point.time_since_epoch();
- auto sec = duration_cast< seconds >( time_from_epoh ).count();*/
-
- //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
-
+
+ for (auto element : arg.blocks) {
+ size += element.block.size();
+ for (auto tx : element.txs)
+ size += tx.size();
+ }
+
+ for (auto element : arg.missed_ids)
+ size += sizeof(element.data);
+
+ size += sizeof(arg.current_blockchain_height);
+ {
+ CRITICAL_REGION_LOCAL(m_buffer_mutex);
+ m_avg_buffer.push_back(size);
+
+ const bool dbg_poke_lock = 0; // debug: try to trigger an error by poking around with locks. TODO: configure option
+ long int dbg_repeat=0;
+ do {
+ m_avg_buffer.push_back(666); // a test value
+ m_avg_buffer.erase_end(1);
+ } while(dbg_poke_lock && (dbg_repeat++)<100000); // in debug/poke mode, repeat this calculation to trigger hidden locking error if there is one
+ }
+ /*using namespace boost::chrono;
+ auto point = steady_clock::now();
+ auto time_from_epoh = point.time_since_epoch();
+ auto sec = duration_cast< seconds >( time_from_epoh ).count();*/
+
+ //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
+
if(context.m_last_response_height > arg.current_blockchain_height)
{
- LOG_ERROR_CCONTEXT("sent wrong NOTIFY_HAVE_OBJECTS: arg.m_current_blockchain_height=" << arg.current_blockchain_height
+ LOG_ERROR_CCONTEXT("sent wrong NOTIFY_HAVE_OBJECTS: arg.m_current_blockchain_height=" << arg.current_blockchain_height
<< " < m_last_response_height=" << context.m_last_response_height << ", dropping connection");
m_p2p->drop_connection(context);
return 1;
@@ -485,14 +485,14 @@ namespace cryptonote
block b;
if(!parse_and_validate_block_from_blob(block_entry.block, b))
{
- LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n"
+ LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n"
<< epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
m_p2p->drop_connection(context);
return 1;
- }
+ }
//to avoid concurrency in core between connections, suspend connections which delivered block later then first one
if(count == 2)
- {
+ {
if(m_core.have_block(get_block_hash(b)))
{
context.m_state = cryptonote_connection_context::state_idle;
@@ -502,18 +502,18 @@ namespace cryptonote
return 1;
}
}
-
+
auto req_it = context.m_requested_objects.find(get_block_hash(b));
if(req_it == context.m_requested_objects.end())
{
- LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
+ LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
<< " wasn't requested, dropping connection");
m_p2p->drop_connection(context);
return 1;
}
- if(b.tx_hashes.size() != block_entry.txs.size())
+ if(b.tx_hashes.size() != block_entry.txs.size())
{
- LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
+ LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
<< ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection");
m_p2p->drop_connection(context);
return 1;
@@ -524,7 +524,7 @@ namespace cryptonote
if(context.m_requested_objects.size())
{
- LOG_PRINT_CCONTEXT_RED("returned not all requested objects (context.m_requested_objects.size()="
+ LOG_PRINT_CCONTEXT_RED("returned not all requested objects (context.m_requested_objects.size()="
<< context.m_requested_objects.size() << "), dropping connection", LOG_LEVEL_0);
m_p2p->drop_connection(context);
return 1;
@@ -537,78 +537,77 @@ namespace cryptonote
boost::bind(&t_core::resume_mine, &m_core));
LOG_PRINT_CCONTEXT_YELLOW( "Got NEW BLOCKS inside of " << __FUNCTION__ << ": size: " << arg.blocks.size() , LOG_LEVEL_1);
-
+
if (m_core.get_test_drop_download() && m_core.get_test_drop_download_height()) { // DISCARD BLOCKS for testing
-
- uint64_t previous_height = m_core.get_current_blockchain_height();
-
- m_core.prepare_handle_incoming_blocks(arg.blocks);
- BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks)
- {
- // process transactions
- TIME_MEASURE_START(transactions_process_time);
- BOOST_FOREACH(auto& tx_blob, block_entry.txs)
- {
- tx_verification_context tvc = AUTO_VAL_INIT(tvc);
- m_core.handle_incoming_tx(tx_blob, tvc, true, true);
- if(tvc.m_verifivation_failed)
- {
- LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = "
- << epee::string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
- m_p2p->drop_connection(context);
- m_core.cleanup_handle_incoming_blocks();
- return 1;
- }
- }
- TIME_MEASURE_FINISH(transactions_process_time);
-
- // process block
-
- TIME_MEASURE_START(block_process_time);
- block_verification_context bvc = boost::value_initialized<block_verification_context>();
-
- m_core.handle_incoming_block(block_entry.block, bvc, false); // <--- process block
-
- if(bvc.m_verifivation_failed)
- {
- LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection");
- m_p2p->drop_connection(context);
- m_p2p->add_ip_fail(context.m_remote_ip);
- m_core.cleanup_handle_incoming_blocks();
- return 1;
- }
- if(bvc.m_marked_as_orphaned)
- {
- LOG_PRINT_CCONTEXT_L1("Block received at sync phase was marked as orphaned, dropping connection");
- m_p2p->drop_connection(context);
- m_p2p->add_ip_fail(context.m_remote_ip);
- m_core.cleanup_handle_incoming_blocks();
- return 1;
- }
-
- TIME_MEASURE_FINISH(block_process_time);
- LOG_PRINT_CCONTEXT_L2("Block process time: " << block_process_time + transactions_process_time << "(" << transactions_process_time << "/" << block_process_time << ")ms");
-
- epee::net_utils::data_logger::get_instance().add_data("calc_time", block_process_time + transactions_process_time);
- epee::net_utils::data_logger::get_instance().add_data("block_processing", 1);
-
-
- } // each download block
- m_core.cleanup_handle_incoming_blocks();
-
- if (m_core.get_current_blockchain_height() > previous_height)
- {
- LOG_PRINT_CCONTEXT_YELLOW( "Synced " << m_core.get_current_blockchain_height() << "/" << m_core.get_target_blockchain_height() , LOG_LEVEL_0);
- }
- } // if not DISCARD BLOCK
-
-
+
+ uint64_t previous_height = m_core.get_current_blockchain_height();
+
+ m_core.prepare_handle_incoming_blocks(arg.blocks);
+ BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks)
+ {
+ // process transactions
+ TIME_MEASURE_START(transactions_process_time);
+ BOOST_FOREACH(auto& tx_blob, block_entry.txs)
+ {
+ tx_verification_context tvc = AUTO_VAL_INIT(tvc);
+ m_core.handle_incoming_tx(tx_blob, tvc, true, true);
+ if(tvc.m_verifivation_failed)
+ {
+ LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = "
+ << epee::string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
+ m_p2p->drop_connection(context);
+ m_core.cleanup_handle_incoming_blocks();
+ return 1;
+ }
+ }
+ TIME_MEASURE_FINISH(transactions_process_time);
+
+ // process block
+
+ TIME_MEASURE_START(block_process_time);
+ block_verification_context bvc = boost::value_initialized<block_verification_context>();
+
+ m_core.handle_incoming_block(block_entry.block, bvc, false); // <--- process block
+
+ if(bvc.m_verifivation_failed)
+ {
+ LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection");
+ m_p2p->drop_connection(context);
+ m_p2p->add_ip_fail(context.m_remote_ip);
+ m_core.cleanup_handle_incoming_blocks();
+ return 1;
+ }
+ if(bvc.m_marked_as_orphaned)
+ {
+ LOG_PRINT_CCONTEXT_L1("Block received at sync phase was marked as orphaned, dropping connection");
+ m_p2p->drop_connection(context);
+ m_p2p->add_ip_fail(context.m_remote_ip);
+ m_core.cleanup_handle_incoming_blocks();
+ return 1;
+ }
+
+ TIME_MEASURE_FINISH(block_process_time);
+ LOG_PRINT_CCONTEXT_L2("Block process time: " << block_process_time + transactions_process_time << "(" << transactions_process_time << "/" << block_process_time << ")ms");
+
+ epee::net_utils::data_logger::get_instance().add_data("calc_time", block_process_time + transactions_process_time);
+ epee::net_utils::data_logger::get_instance().add_data("block_processing", 1);
+
+ } // each download block
+ m_core.cleanup_handle_incoming_blocks();
+
+ if (m_core.get_current_blockchain_height() > previous_height)
+ {
+ LOG_PRINT_CCONTEXT_YELLOW( "Synced " << m_core.get_current_blockchain_height() << "/" << m_core.get_target_blockchain_height() , LOG_LEVEL_0);
+ }
+ } // if not DISCARD BLOCK
+
+
}
request_missing_objects(context, true);
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::on_idle()
{
return m_core.on_idle();
@@ -629,18 +628,18 @@ namespace cryptonote
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::request_missing_objects(cryptonote_connection_context& context, bool check_having_blocks)
{
- //if (!m_one_request == false)
- //return true;
- m_one_request = false;
- // save request size to log (dr monero)
- /*using namespace boost::chrono;
- auto point = steady_clock::now();
- auto time_from_epoh = point.time_since_epoch();
- auto sec = duration_cast< seconds >( time_from_epoh ).count();*/
-
+ //if (!m_one_request == false)
+ //return true;
+ m_one_request = false;
+ // save request size to log (dr monero)
+ /*using namespace boost::chrono;
+ auto point = steady_clock::now();
+ auto time_from_epoh = point.time_since_epoch();
+ auto sec = duration_cast< seconds >( time_from_epoh ).count();*/
+
if(context.m_needed_objects.size())
{
//we know objects that we need, request this objects
@@ -648,8 +647,8 @@ namespace cryptonote
size_t count = 0;
auto it = context.m_needed_objects.begin();
- size_t count_limit = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
- _note_c("net/req-calc" , "Setting count_limit: " << count_limit);
+ size_t count_limit = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
+ _note_c("net/req-calc" , "Setting count_limit: " << count_limit);
while(it != context.m_needed_objects.end() && count < BLOCKS_SYNCHRONIZING_DEFAULT_COUNT)
{
if( !(check_having_blocks && m_core.have_block(*it)))
@@ -661,35 +660,35 @@ namespace cryptonote
context.m_needed_objects.erase(it++);
}
LOG_PRINT_CCONTEXT_L1("-->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()=" << req.blocks.size() << ", txs.size()=" << req.txs.size()
- << "requested blocks count=" << count << " / " << count_limit);
- //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
-
- post_notify<NOTIFY_REQUEST_GET_OBJECTS>(req, context);
+ << "requested blocks count=" << count << " / " << count_limit);
+ //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
+
+ post_notify<NOTIFY_REQUEST_GET_OBJECTS>(req, context);
}else if(context.m_last_response_height < context.m_remote_blockchain_height-1)
{//we have to fetch more objects ids, request blockchain entry
-
+
NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized<NOTIFY_REQUEST_CHAIN::request>();
m_core.get_short_chain_history(r.block_ids);
- handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
-
- //std::string blob; // for calculate size of request
- //epee::serialization::store_t_to_binary(r, blob);
- //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
- LOG_PRINT_CCONTEXT_L1("r = " << 200);
-
+ handler_request_blocks_history( r.block_ids ); // change the limit(?), sleep(?)
+
+ //std::string blob; // for calculate size of request
+ //epee::serialization::store_t_to_binary(r, blob);
+ //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size());
+ LOG_PRINT_CCONTEXT_L1("r = " << 200);
+
LOG_PRINT_CCONTEXT_L1("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
}else
- {
- CHECK_AND_ASSERT_MES(context.m_last_response_height == context.m_remote_blockchain_height-1
- && !context.m_needed_objects.size()
- && !context.m_requested_objects.size(), false, "request_missing_blocks final condition failed!"
+ {
+ CHECK_AND_ASSERT_MES(context.m_last_response_height == context.m_remote_blockchain_height-1
+ && !context.m_needed_objects.size()
+ && !context.m_requested_objects.size(), false, "request_missing_blocks final condition failed!"
<< "\r\nm_last_response_height=" << context.m_last_response_height
<< "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height
<< "\r\nm_needed_objects.size()=" << context.m_needed_objects.size()
<< "\r\nm_requested_objects.size()=" << context.m_requested_objects.size()
<< "\r\non connection [" << epee::net_utils::print_connection_context_short(context)<< "]");
-
+
context.m_state = cryptonote_connection_context::state_normal;
LOG_PRINT_CCONTEXT_GREEN(" SYNCHRONIZED OK", LOG_LEVEL_0);
on_connection_synchronized();
@@ -697,16 +696,16 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::on_connection_synchronized()
{
bool val_expected = false;
if(m_synchronized.compare_exchange_strong(val_expected, true))
{
- LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL
- << "You are now synchronized with the network. You may now start simplewallet." << ENDL
+ LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL
+ << "You are now synchronized with the network. You may now start simplewallet." << ENDL
<< ENDL
- << "Please note, that the blockchain will be saved only after you quit the daemon with \"exit\" command or if you use \"save\" command." << ENDL
+ << "Please note, that the blockchain will be saved only after you quit the daemon with \"exit\" command or if you use \"save\" command." << ENDL
<< "Otherwise, you will possibly need to synchronize the blockchain again." << ENDL
<< ENDL
<< "Use \"help\" command to see the list of available commands." << ENDL
@@ -716,7 +715,7 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
size_t t_cryptonote_protocol_handler<t_core>::get_synchronizing_connections_count()
{
size_t count = 0;
@@ -728,12 +727,12 @@ namespace cryptonote
return count;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, cryptonote_connection_context& context)
{
- LOG_PRINT_CCONTEXT_L2("NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()=" << arg.m_block_ids.size()
+ LOG_PRINT_CCONTEXT_L2("NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()=" << arg.m_block_ids.size()
<< ", m_start_height=" << arg.start_height << ", m_total_height=" << arg.total_height);
-
+
if(!arg.m_block_ids.size())
{
LOG_ERROR_CCONTEXT("sent empty m_block_ids, dropping connection");
@@ -750,7 +749,7 @@ namespace cryptonote
m_p2p->add_ip_fail(context.m_remote_ip);
return 1;
}
-
+
context.m_remote_blockchain_height = arg.total_height;
context.m_last_response_height = arg.start_height + arg.m_block_ids.size()-1;
if(context.m_last_response_height > context.m_remote_blockchain_height)
@@ -771,29 +770,29 @@ namespace cryptonote
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)
{
return relay_post_notify<NOTIFY_NEW_BLOCK>(arg, exclude_context);
}
//------------------------------------------------------------------------------------------------------------------------
- template<class t_core>
+ template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context)
{
return relay_post_notify<NOTIFY_NEW_TRANSACTIONS>(arg, exclude_context);
}
- /// @deprecated
- template<class t_core> std::ofstream& t_cryptonote_protocol_handler<t_core>::get_logreq() const {
- static std::ofstream * logreq=NULL;
- if (!logreq) {
- LOG_PRINT_RED("LOG OPENED",LOG_LEVEL_0);
- logreq = new std::ofstream("logreq.txt"); // leak mem (singleton)
- *logreq << "Opened log" << std::endl;
- }
- LOG_PRINT_YELLOW("LOG USED",LOG_LEVEL_0);
- (*logreq) << "log used" << std::endl;
- return *logreq;
- }
+ /// @deprecated
+ template<class t_core> std::ofstream& t_cryptonote_protocol_handler<t_core>::get_logreq() const {
+ static std::ofstream * logreq=NULL;
+ if (!logreq) {
+ LOG_PRINT_RED("LOG OPENED",LOG_LEVEL_0);
+ logreq = new std::ofstream("logreq.txt"); // leak mem (singleton)
+ *logreq << "Opened log" << std::endl;
+ }
+ LOG_PRINT_YELLOW("LOG USED",LOG_LEVEL_0);
+ (*logreq) << "log used" << std::endl;
+ return *logreq;
+ }
} // namespace
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index 90befa8d1..6358bb3ff 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -28,12 +28,12 @@
set(blocksdat "")
if(PER_BLOCK_CHECKPOINT)
- if(APPLE)
- add_custom_command(OUTPUT blocksdat.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ld -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
- else()
- add_custom_command(OUTPUT blocksdat.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ld -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
- endif()
- set(blocksdat "blocksdat.o")
+ if(APPLE)
+ add_custom_command(OUTPUT blocksdat.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ld -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
+ else()
+ add_custom_command(OUTPUT blocksdat.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ld -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
+ endif()
+ set(blocksdat "blocksdat.o")
endif()
set(daemon_sources
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 68e375269..63d25ef1c 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -51,8 +51,8 @@ int main(int argc, char const * argv[])
{
try {
- _note_c("dbg/main", "Begin of main()");
- // TODO parse the debug options like set log level right here at start
+ _note_c("dbg/main", "Begin of main()");
+ // TODO parse the debug options like set log level right here at start
tools::sanitize_locale();
@@ -77,7 +77,7 @@ int main(int argc, char const * argv[])
command_line::add_arg(visible_options, daemon_args::arg_config_file, default_conf.string());
command_line::add_arg(visible_options, command_line::arg_test_dbg_lock_sleep);
cryptonote::core::init_options(core_settings);
-
+
// Settings
bf::path default_log = default_data_dir / std::string(CRYPTONOTE_NAME ".log");
command_line::add_arg(core_settings, daemon_args::arg_log_file, default_log.string());
@@ -132,7 +132,7 @@ int main(int argc, char const * argv[])
std::cout << "OS: " << tools::get_os_version_string() << ENDL;
return 0;
}
-
+
epee::g_test_dbg_lock_sleep = command_line::get_arg(vm, command_line::arg_test_dbg_lock_sleep);
std::string db_type = command_line::get_arg(vm, command_line::arg_db_type);
@@ -261,7 +261,7 @@ int main(int argc, char const * argv[])
);
}
- _note_c("dbg/main", "Moving from main() into the daemonize now.");
+ _note_c("dbg/main", "Moving from main() into the daemonize now.");
return daemonizer::daemonize(argc, argv, daemonize::t_executor{}, vm);
}
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 99f12beed..772973d6b 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
@@ -83,15 +83,15 @@ namespace nodetool
typedef t_payload_net_handler payload_net_handler;
node_server(t_payload_net_handler& payload_handler)
- :m_payload_handler(payload_handler),
+ :m_payload_handler(payload_handler),
m_current_number_of_out_peers(0),
- m_allow_local_ip(false),
- m_hide_my_port(false),
+ m_allow_local_ip(false),
+ m_hide_my_port(false),
m_no_igd(false),
m_offline(false),
m_save_graph(false),
is_closing(false),
- m_net_server( epee::net_utils::e_connection_type_P2P ) // this is a P2P connection of the main p2p node server, because this is class node_server<>
+ m_net_server( epee::net_utils::e_connection_type_P2P ) // this is a P2P connection of the main p2p node server, because this is class node_server<>
{}
virtual ~node_server()
{}
@@ -128,7 +128,7 @@ namespace nodetool
, "seeds.moneroseeds.ch"
, "seeds.moneroseeds.li"
};
-
+
bool islimitup=false;
bool islimitdown=false;
@@ -201,7 +201,7 @@ namespace nodetool
bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, bool white = true);
size_t get_random_index_with_fixed_probability(size_t max_index);
bool is_peer_used(const peerlist_entry& peer);
- bool is_addr_connected(const net_address& peer);
+ bool is_addr_connected(const net_address& peer);
template<class t_callback>
bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb);
bool make_expected_connections_count(bool white_list, size_t expected_connections);
@@ -215,20 +215,20 @@ namespace nodetool
template <class Container>
bool parse_peers_and_add_to_container(const boost::program_options::variables_map& vm, const command_line::arg_descriptor<std::vector<std::string> > & arg, Container& container);
- bool set_max_out_peers(const boost::program_options::variables_map& vm, int64_t max);
- bool set_tos_flag(const boost::program_options::variables_map& vm, int limit);
-
- bool set_rate_up_limit(const boost::program_options::variables_map& vm, int64_t limit);
- bool set_rate_down_limit(const boost::program_options::variables_map& vm, int64_t limit);
- bool set_rate_limit(const boost::program_options::variables_map& vm, int64_t limit);
+ bool set_max_out_peers(const boost::program_options::variables_map& vm, int64_t max);
+ bool set_tos_flag(const boost::program_options::variables_map& vm, int limit);
+
+ bool set_rate_up_limit(const boost::program_options::variables_map& vm, int64_t limit);
+ bool set_rate_down_limit(const boost::program_options::variables_map& vm, int64_t limit);
+ bool set_rate_limit(const boost::program_options::variables_map& vm, int64_t limit);
void kill() { ///< will be called e.g. from deinit()
- _info("Killing the net_node");
- is_closing = true;
- if(mPeersLoggerThread != nullptr)
- mPeersLoggerThread->join(); // make sure the thread finishes
- _info("Joined extra background net_node threads");
- }
+ _info("Killing the net_node");
+ is_closing = true;
+ if(mPeersLoggerThread != nullptr)
+ mPeersLoggerThread->join(); // make sure the thread finishes
+ _info("Joined extra background net_node threads");
+ }
//debug functions
std::string print_connections_container();
@@ -247,16 +247,16 @@ namespace nodetool
END_KV_SERIALIZE_MAP()
};
- public:
+ public:
config m_config; // TODO was private, add getters?
std::atomic<unsigned int> m_current_number_of_out_peers;
- void set_save_graph(bool save_graph)
- {
- m_save_graph = save_graph;
- epee::net_utils::connection_basic::set_save_graph(save_graph);
- }
- private:
+ void set_save_graph(bool save_graph)
+ {
+ m_save_graph = save_graph;
+ epee::net_utils::connection_basic::set_save_graph(save_graph);
+ }
+ private:
std::string m_config_folder;
bool m_have_address;
@@ -270,7 +270,7 @@ namespace nodetool
bool m_offline;
std::atomic<bool> m_save_graph;
std::atomic<bool> is_closing;
- std::unique_ptr<std::thread> mPeersLoggerThread;
+ std::unique_ptr<std::thread> mPeersLoggerThread;
//critical_section m_connections_lock;
//connections_indexed_container m_connections;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 43ccd8679..ef733416d 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -1,21 +1,21 @@
// Copyright (c) 2014-2015, The Monero Project
-//
+//
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
-//
+//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
-//
+//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
-//
+//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
+//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
// IP blocking adapted from Boolberry
@@ -34,7 +34,7 @@
#include <algorithm>
#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/thread/thread.hpp>
+#include <boost/thread/thread.hpp>
#include <atomic>
#include "version.h"
@@ -89,17 +89,17 @@ namespace nodetool
" If this option is given the options add-priority-node and seed-node are ignored"};
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
-
- const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
- const command_line::arg_descriptor<bool> arg_offline = {"offline", "Do not listen for peers, nor connect to any"};
- const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max limit of out peers", -1};
- const command_line::arg_descriptor<int> arg_tos_flag = {"tos-flag", "set TOS flag", -1};
-
- const command_line::arg_descriptor<int64_t> arg_limit_rate_up = {"limit-rate-up", "set limit-rate-up [kB/s]", -1};
- const command_line::arg_descriptor<int64_t> arg_limit_rate_down = {"limit-rate-down", "set limit-rate-down [kB/s]", -1};
- const command_line::arg_descriptor<int64_t> arg_limit_rate = {"limit-rate", "set limit-rate [kB/s]", -1};
-
- const command_line::arg_descriptor<bool> arg_save_graph = {"save-graph", "Save data for dr monero", false};
+
+ const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
+ const command_line::arg_descriptor<bool> arg_offline = {"offline", "Do not listen for peers, nor connect to any"};
+ const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max limit of out peers", -1};
+ const command_line::arg_descriptor<int> arg_tos_flag = {"tos-flag", "set TOS flag", -1};
+
+ const command_line::arg_descriptor<int64_t> arg_limit_rate_up = {"limit-rate-up", "set limit-rate-up [kB/s]", -1};
+ const command_line::arg_descriptor<int64_t> arg_limit_rate_down = {"limit-rate-down", "set limit-rate-down [kB/s]", -1};
+ const command_line::arg_descriptor<int64_t> arg_limit_rate = {"limit-rate", "set limit-rate [kB/s]", -1};
+
+ const command_line::arg_descriptor<bool> arg_save_graph = {"save-graph", "Save data for dr monero", false};
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
@@ -113,7 +113,7 @@ namespace nodetool
command_line::add_arg(desc, arg_p2p_add_peer);
command_line::add_arg(desc, arg_p2p_add_priority_node);
command_line::add_arg(desc, arg_p2p_add_exclusive_node);
- command_line::add_arg(desc, arg_p2p_seed_node);
+ command_line::add_arg(desc, arg_p2p_seed_node);
command_line::add_arg(desc, arg_p2p_hide_my_port);
command_line::add_arg(desc, arg_no_igd);
command_line::add_arg(desc, arg_offline);
@@ -254,7 +254,7 @@ namespace nodetool
m_offline = command_line::get_arg(vm, arg_offline);
if (command_line::has_arg(vm, arg_p2p_add_peer))
- {
+ {
std::vector<std::string> perrs = command_line::get_arg(vm, arg_p2p_add_peer);
for(const std::string& pr_str: perrs)
{
@@ -265,24 +265,24 @@ namespace nodetool
m_command_line_peers.push_back(pe);
}
}
-
+
if(command_line::has_arg(vm, arg_save_graph))
{
- set_save_graph(true);
- }
+ set_save_graph(true);
+ }
if (command_line::has_arg(vm,arg_p2p_add_exclusive_node))
{
if (!parse_peers_and_add_to_container(vm, arg_p2p_add_exclusive_node, m_exclusive_peers))
return false;
}
-
+
if (command_line::has_arg(vm, arg_p2p_add_priority_node))
{
if (!parse_peers_and_add_to_container(vm, arg_p2p_add_priority_node, m_priority_peers))
return false;
}
-
+
if (command_line::has_arg(vm, arg_p2p_seed_node))
{
if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, m_seed_nodes))
@@ -291,21 +291,21 @@ namespace nodetool
if(command_line::has_arg(vm, arg_p2p_hide_my_port))
m_hide_my_port = true;
-
+
if ( !set_max_out_peers(vm, command_line::get_arg(vm, arg_out_peers) ) )
- return false;
-
- if ( !set_tos_flag(vm, command_line::get_arg(vm, arg_tos_flag) ) )
- return false;
+ return false;
- if ( !set_rate_up_limit(vm, command_line::get_arg(vm, arg_limit_rate_up) ) )
- return false;
+ if ( !set_tos_flag(vm, command_line::get_arg(vm, arg_tos_flag) ) )
+ return false;
- if ( !set_rate_down_limit(vm, command_line::get_arg(vm, arg_limit_rate_down) ) )
- return false;
+ if ( !set_rate_up_limit(vm, command_line::get_arg(vm, arg_limit_rate_up) ) )
+ return false;
- if ( !set_rate_limit(vm, command_line::get_arg(vm, arg_limit_rate) ) )
- return false;
+ if ( !set_rate_down_limit(vm, command_line::get_arg(vm, arg_limit_rate_down) ) )
+ return false;
+
+ if ( !set_rate_limit(vm, command_line::get_arg(vm, arg_limit_rate) ) )
+ return false;
return true;
}
@@ -370,7 +370,7 @@ namespace nodetool
// add the result addresses as seed nodes
// TODO: at some point add IPv6 support, but that won't be relevant
// for some time yet.
-
+
std::vector<std::vector<std::string>> dns_results;
dns_results.resize(m_seed_nodes_list.size());
@@ -484,7 +484,7 @@ namespace nodetool
for(auto& p: m_command_line_peers)
m_peerlist.append_with_peer_white(p);
-
+
//only in case if we really sure that we have external visible ip
m_have_address = true;
m_ip_address = 0;
@@ -512,48 +512,48 @@ namespace nodetool
// Add UPnP port mapping
if(m_no_igd == false) {
- LOG_PRINT_L0("Attempting to add IGD port mapping.");
- int result;
+ LOG_PRINT_L0("Attempting to add IGD port mapping.");
+ int result;
#if MINIUPNPC_API_VERSION > 13
- // default according to miniupnpc.h
- unsigned char ttl = 2;
- UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, ttl, &result);
+ // default according to miniupnpc.h
+ unsigned char ttl = 2;
+ UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, ttl, &result);
#else
- UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, &result);
+ UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, &result);
#endif
- UPNPUrls urls;
- IGDdatas igdData;
- char lanAddress[64];
- result = UPNP_GetValidIGD(deviceList, &urls, &igdData, lanAddress, sizeof lanAddress);
- freeUPNPDevlist(deviceList);
- if (result != 0) {
- if (result == 1) {
- std::ostringstream portString;
- portString << m_listenning_port;
-
- // Delete the port mapping before we create it, just in case we have dangling port mapping from the daemon not being shut down correctly
- UPNP_DeletePortMapping(urls.controlURL, igdData.first.servicetype, portString.str().c_str(), "TCP", 0);
-
- int portMappingResult;
- portMappingResult = UPNP_AddPortMapping(urls.controlURL, igdData.first.servicetype, portString.str().c_str(), portString.str().c_str(), lanAddress, CRYPTONOTE_NAME, "TCP", 0, "0");
- if (portMappingResult != 0) {
- LOG_ERROR("UPNP_AddPortMapping failed, error: " << strupnperror(portMappingResult));
- } else {
- LOG_PRINT_GREEN("Added IGD port mapping.", LOG_LEVEL_0);
- }
- } else if (result == 2) {
- LOG_PRINT_L0("IGD was found but reported as not connected.");
- } else if (result == 3) {
- LOG_PRINT_L0("UPnP device was found but not recoginzed as IGD.");
- } else {
- LOG_ERROR("UPNP_GetValidIGD returned an unknown result code.");
- }
-
- FreeUPNPUrls(&urls);
- } else {
- LOG_PRINT_L0("No IGD was found.");
- }
- }
+ UPNPUrls urls;
+ IGDdatas igdData;
+ char lanAddress[64];
+ result = UPNP_GetValidIGD(deviceList, &urls, &igdData, lanAddress, sizeof lanAddress);
+ freeUPNPDevlist(deviceList);
+ if (result != 0) {
+ if (result == 1) {
+ std::ostringstream portString;
+ portString << m_listenning_port;
+
+ // Delete the port mapping before we create it, just in case we have dangling port mapping from the daemon not being shut down correctly
+ UPNP_DeletePortMapping(urls.controlURL, igdData.first.servicetype, portString.str().c_str(), "TCP", 0);
+
+ int portMappingResult;
+ portMappingResult = UPNP_AddPortMapping(urls.controlURL, igdData.first.servicetype, portString.str().c_str(), portString.str().c_str(), lanAddress, CRYPTONOTE_NAME, "TCP", 0, "0");
+ if (portMappingResult != 0) {
+ LOG_ERROR("UPNP_AddPortMapping failed, error: " << strupnperror(portMappingResult));
+ } else {
+ LOG_PRINT_GREEN("Added IGD port mapping.", LOG_LEVEL_0);
+ }
+ } else if (result == 2) {
+ LOG_PRINT_L0("IGD was found but reported as not connected.");
+ } else if (result == 3) {
+ LOG_PRINT_L0("UPnP device was found but not recoginzed as IGD.");
+ } else {
+ LOG_ERROR("UPNP_GetValidIGD returned an unknown result code.");
+ }
+
+ FreeUPNPUrls(&urls);
+ } else {
+ LOG_PRINT_L0("No IGD was found.");
+ }
+ }
return res;
}
//-----------------------------------------------------------------------------------
@@ -566,30 +566,30 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::run()
{
- // creating thread to log number of connections
- mPeersLoggerThread.reset(new std::thread([&]()
- {
- _note("Thread monitor number of peers - start");
- while (!is_closing)
- { // main loop of thread
- //number_of_peers = m_net_server.get_config_object().get_connections_count();
- unsigned int number_of_peers = 0;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
- {
- if (!cntxt.m_is_income) ++number_of_peers;
- return true;
- }); // lambda
-
- m_current_number_of_out_peers = number_of_peers;
- if (epee::net_utils::data_logger::is_dying())
- break;
- epee::net_utils::data_logger::get_instance().add_data("peers", number_of_peers);
-
- std::this_thread::sleep_for(std::chrono::seconds(1));
- } // main loop of thread
- _note("Thread monitor number of peers - done");
- })); // lambda
-
+ // creating thread to log number of connections
+ mPeersLoggerThread.reset(new std::thread([&]()
+ {
+ _note("Thread monitor number of peers - start");
+ while (!is_closing)
+ { // main loop of thread
+ //number_of_peers = m_net_server.get_config_object().get_connections_count();
+ unsigned int number_of_peers = 0;
+ m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ {
+ if (!cntxt.m_is_income) ++number_of_peers;
+ return true;
+ }); // lambda
+
+ m_current_number_of_out_peers = number_of_peers;
+ if (epee::net_utils::data_logger::is_dying())
+ break;
+ epee::net_utils::data_logger::get_instance().add_data("peers", number_of_peers);
+
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ } // main loop of thread
+ _note("Thread monitor number of peers - done");
+ })); // lambda
+
//here you can set worker threads count
int thrds_count = 10;
@@ -620,7 +620,7 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::deinit()
{
- kill();
+ kill();
m_peerlist.deinit();
m_net_server.deinit_server();
return store_config();
@@ -662,7 +662,7 @@ namespace nodetool
return true;
}
//-----------------------------------------------------------------------------------
-
+
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context_, bool just_take_peerlist)
@@ -671,11 +671,11 @@ namespace nodetool
typename COMMAND_HANDSHAKE::response rsp;
get_local_node_data(arg.node_data);
m_payload_handler.get_payload_sync_data(arg.payload_data);
-
+
epee::simple_event ev;
std::atomic<bool> hsh_result(false);
-
- bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(),
+
+ bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(),
[this, &pi, &ev, &hsh_result, &just_take_peerlist](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
{
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ev.raise();});
@@ -744,7 +744,7 @@ namespace nodetool
typename COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg);
m_payload_handler.get_payload_sync_data(arg.payload_data);
- bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_TIMED_SYNC::response>(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(),
+ bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_TIMED_SYNC::response>(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(),
[this](int code, const typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context)
{
if(code < 0)
@@ -835,16 +835,16 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, bool white)
{
- if (m_current_number_of_out_peers == m_config.m_net_config.connections_count) // out peers limit
- {
- return false;
- }
- else if (m_current_number_of_out_peers > m_config.m_net_config.connections_count)
- {
- m_net_server.get_config_object().del_out_connections(1);
- m_current_number_of_out_peers --; // atomic variable, update time = 1s
- return false;
- }
+ if (m_current_number_of_out_peers == m_config.m_net_config.connections_count) // out peers limit
+ {
+ return false;
+ }
+ else if (m_current_number_of_out_peers > m_config.m_net_config.connections_count)
+ {
+ m_net_server.get_config_object().del_out_connections(1);
+ m_current_number_of_out_peers --; // atomic variable, update time = 1s
+ return false;
+ }
LOG_PRINT_L1("Connecting to " << epee::string_tools::get_ip_string_from_int32(na.ip) << ":"
<< epee::string_tools::num_to_string_fast(na.port) << "(white=" << white << ", last_seen: "
<< (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
@@ -946,12 +946,12 @@ namespace nodetool
++try_count;
- _note("Considering connecting (out) to peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port));
+ _note("Considering connecting (out) to peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port));
if(is_peer_used(pe)) {
- _note("Peer is used");
+ _note("Peer is used");
continue;
- }
+ }
if(!is_remote_ip_allowed(pe.adr.ip))
continue;
@@ -963,11 +963,11 @@ namespace nodetool
<< ":" << boost::lexical_cast<std::string>(pe.adr.port)
<< "[white=" << use_white_list
<< "] last_seen: " << (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never"));
-
+
if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, pe.last_seen, use_white_list)) {
- _note("Handshake failed");
+ _note("Handshake failed");
continue;
- }
+ }
return true;
}
@@ -986,7 +986,7 @@ namespace nodetool
size_t try_count = 0;
size_t current_index = crypto::rand<size_t>()%m_seed_nodes.size();
while(true)
- {
+ {
if(m_net_server.is_stop_signal_sent())
return false;
@@ -1135,7 +1135,7 @@ namespace nodetool
node_data.peer_id = m_config.m_peer_id;
if(!m_hide_my_port)
node_data.my_port = m_external_port ? m_external_port : m_listenning_port;
- else
+ else
node_data.my_port = 0;
node_data.network_id = m_network_id;
return true;
@@ -1515,92 +1515,92 @@ namespace nodetool
return true;
}
-
+
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::set_max_out_peers(const boost::program_options::variables_map& vm, int64_t max)
- {
- if(max == -1) {
- m_config.m_net_config.connections_count = P2P_DEFAULT_CONNECTIONS_COUNT;
- epee::net_utils::data_logger::get_instance().add_data("peers_limit", m_config.m_net_config.connections_count);
- return true;
- }
- epee::net_utils::data_logger::get_instance().add_data("peers_limit", max);
- m_config.m_net_config.connections_count = max;
- return true;
- }
-
+ {
+ if(max == -1) {
+ m_config.m_net_config.connections_count = P2P_DEFAULT_CONNECTIONS_COUNT;
+ epee::net_utils::data_logger::get_instance().add_data("peers_limit", m_config.m_net_config.connections_count);
+ return true;
+ }
+ epee::net_utils::data_logger::get_instance().add_data("peers_limit", max);
+ m_config.m_net_config.connections_count = max;
+ return true;
+ }
+
template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::delete_connections(size_t count)
{
- m_net_server.get_config_object().del_out_connections(count);
+ m_net_server.get_config_object().del_out_connections(count);
}
-
- template<class t_payload_net_handler>
+
+ template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::set_tos_flag(const boost::program_options::variables_map& vm, int flag)
- {
- if(flag==-1){
- return true;
- }
- epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_tos_flag(flag);
- _dbg1("Set ToS flag " << flag);
- return true;
- }
-
- template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::set_rate_up_limit(const boost::program_options::variables_map& vm, int64_t limit)
- {
- this->islimitup=true;
-
- if (limit==-1) {
- limit=default_limit_up;
- this->islimitup=false;
- }
-
- limit *= 1024;
- epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_up_limit( limit );
- LOG_PRINT_L0("Set limit-up to " << limit/1024 << " kB/s");
- return true;
- }
-
+ {
+ if(flag==-1){
+ return true;
+ }
+ epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_tos_flag(flag);
+ _dbg1("Set ToS flag " << flag);
+ return true;
+ }
+
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::set_rate_down_limit(const boost::program_options::variables_map& vm, int64_t limit)
- {
- this->islimitdown=true;
- if(limit==-1) {
- limit=default_limit_down;
- this->islimitdown=false;
- }
- limit *= 1024;
- epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_down_limit( limit );
- LOG_PRINT_L0("Set limit-down to " << limit/1024 << " kB/s");
- return true;
- }
+ bool node_server<t_payload_net_handler>::set_rate_up_limit(const boost::program_options::variables_map& vm, int64_t limit)
+ {
+ this->islimitup=true;
+
+ if (limit==-1) {
+ limit=default_limit_up;
+ this->islimitup=false;
+ }
+
+ limit *= 1024;
+ epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_up_limit( limit );
+ LOG_PRINT_L0("Set limit-up to " << limit/1024 << " kB/s");
+ return true;
+ }
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::set_rate_limit(const boost::program_options::variables_map& vm, int64_t limit)
- {
- int64_t limit_up = 0;
- int64_t limit_down = 0;
-
- if(limit == -1)
- {
- limit_up = default_limit_up * 1024;
- limit_down = default_limit_down * 1024;
- }
- else
- {
- limit_up = limit * 1024;
- limit_down = limit * 1024;
- }
- if(!this->islimitup) {
- epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_up_limit(limit_up);
- LOG_PRINT_L0("Set limit-up to " << limit_up/1024 << " kB/s");
- }
- if(!this->islimitdown) {
- epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_down_limit(limit_down);
- LOG_PRINT_L0("Set limit-down to " << limit_down/1024 << " kB/s");
- }
+ bool node_server<t_payload_net_handler>::set_rate_down_limit(const boost::program_options::variables_map& vm, int64_t limit)
+ {
+ this->islimitdown=true;
+ if(limit==-1) {
+ limit=default_limit_down;
+ this->islimitdown=false;
+ }
+ limit *= 1024;
+ epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_down_limit( limit );
+ LOG_PRINT_L0("Set limit-down to " << limit/1024 << " kB/s");
+ return true;
+ }
+
+ template<class t_payload_net_handler>
+ bool node_server<t_payload_net_handler>::set_rate_limit(const boost::program_options::variables_map& vm, int64_t limit)
+ {
+ int64_t limit_up = 0;
+ int64_t limit_down = 0;
- return true;
- }
+ if(limit == -1)
+ {
+ limit_up = default_limit_up * 1024;
+ limit_down = default_limit_down * 1024;
+ }
+ else
+ {
+ limit_up = limit * 1024;
+ limit_down = limit * 1024;
+ }
+ if(!this->islimitup) {
+ epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_up_limit(limit_up);
+ LOG_PRINT_L0("Set limit-up to " << limit_up/1024 << " kB/s");
+ }
+ if(!this->islimitdown) {
+ epee::net_utils::connection<epee::levin::async_protocol_handler<p2p_connection_context> >::set_rate_down_limit(limit_down);
+ LOG_PRINT_L0("Set limit-down to " << limit_down/1024 << " kB/s");
+ }
+
+ return true;
+ }
}
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 5a9b96bb8..8fc07db2c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -48,6 +48,7 @@ using namespace epee;
#include "cryptonote_protocol/blobdatatype.h"
#include "mnemonics/electrum-words.h"
#include "common/dns_utils.h"
+#include "common/util.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
@@ -1283,8 +1284,20 @@ void wallet2::store()
std::string buf;
bool r = ::serialization::dump_binary(cache_file_data, buf);
- r = r && epee::file_io_utils::save_string_to_file(m_wallet_file, buf);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file);
+
+ // save to new file, rename main to old, rename new to main
+ // at all times, there should be a valid file on disk
+ const std::string new_file = m_wallet_file + ".new";
+ const std::string old_file = m_wallet_file + ".old";
+ r = epee::file_io_utils::save_string_to_file(new_file, buf);
+ THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, new_file);
+ boost::filesystem::remove(old_file); // probably does not exist
+ std::error_code e = tools::replace_file(m_wallet_file, old_file);
+ THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e);
+ e = tools::replace_file(new_file, m_wallet_file);
+ THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e);
+ boost::filesystem::remove(old_file);
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::unlocked_balance() const
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
index 94518e691..dd13343ed 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -192,6 +192,12 @@ namespace tools
{
}
+ explicit file_error_base(std::string&& loc, const std::string& file, const std::error_code &e)
+ : wallet_logic_error(std::move(loc), std::string(file_error_messages[msg_index]) + " \"" + file + "\": " + e.message())
+ , m_file(file)
+ {
+ }
+
const std::string& file() const { return m_file; }
std::string to_string() const { return wallet_logic_error::to_string(); }