aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt97
-rw-r--r--README.md10
-rw-r--r--contrib/epee/include/misc_log_ex.h44
-rw-r--r--src/CMakeLists.txt16
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.cpp6
-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/blockchain_utilities/blockchain_import.cpp2
-rw-r--r--src/blockchain_utilities/bootstrap_file.cpp2
-rw-r--r--src/blocks/blockexports.c16
-rw-r--r--src/common/dns_utils.cpp77
-rw-r--r--src/common/scoped_message_writer.h2
-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.cpp4544
-rw-r--r--src/cryptonote_core/blockchain.h66
-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/hardfork.cpp12
-rw-r--r--src/cryptonote_core/hardfork.h8
-rw-r--r--src/cryptonote_core/miner.cpp31
-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-base.cpp2
-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/daemon/rpc_command_executor.cpp1
-rw-r--r--src/p2p/net_node.h66
-rw-r--r--src/p2p/net_node.inl410
-rw-r--r--src/rpc/core_rpc_server.cpp11
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h4
-rw-r--r--src/simplewallet/simplewallet.cpp2
-rw-r--r--src/wallet/wallet2.cpp56
-rw-r--r--src/wallet/wallet2.h11
-rw-r--r--src/wallet/wallet_errors.h6
43 files changed, 3741 insertions, 3630 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aef7a52e6..b6a6defa0 100644
--- a/CMakeLists.txt
+++ b/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
cmake_minimum_required(VERSION 2.8.7)
@@ -46,30 +46,30 @@ function (die msg)
endfunction ()
if (NOT ${ARCH} STREQUAL "")
- string(SUBSTRING ${ARCH} 0 3 IS_ARM)
- string(TOLOWER ${IS_ARM} IS_ARM)
-
- if (${IS_ARM} STREQUAL "arm")
- string(SUBSTRING ${ARCH} 0 5 ARM_TEST)
- string(TOLOWER ${ARM_TEST} ARM_TEST)
-
- if (${ARM_TEST} STREQUAL "armv6")
- set(ARM6 1)
- else()
- set(ARM6 0)
- endif()
-
- if (${ARM_TEST} STREQUAL "armv7")
- set(ARM7 1)
- else()
- set(ARM7 0)
- endif()
- endif()
+ string(SUBSTRING ${ARCH} 0 3 IS_ARM)
+ string(TOLOWER ${IS_ARM} IS_ARM)
+
+ if (${IS_ARM} STREQUAL "arm")
+ string(SUBSTRING ${ARCH} 0 5 ARM_TEST)
+ string(TOLOWER ${ARM_TEST} ARM_TEST)
+
+ if (${ARM_TEST} STREQUAL "armv6")
+ set(ARM6 1)
+ else()
+ set(ARM6 0)
+ endif()
+
+ if (${ARM_TEST} STREQUAL "armv7")
+ set(ARM7 1)
+ else()
+ set(ARM7 0)
+ endif()
+ endif()
endif()
if(WIN32 OR ARM7 OR ARM6)
- set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
- set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
+ set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
+ set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
endif()
# set this to 0 if per-block checkpoint needs to be disabled
@@ -137,7 +137,7 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "DragonFly.*|FreeBSD")
endif()
# TODO: check bsdi, NetBSD, OpenBSD, to see if they need the same FreeBSD changes
-#
+#
# elseif(CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*")
# set(NETBSD TRUE)
# elseif(CMAKE_SYSTEM_NAME MATCHES "kOpenBSD.*|OpenBSD.*")
@@ -194,27 +194,27 @@ endif()
set(BERKELEY_DB 0)
if (DATABASE STREQUAL "lmdb")
set(BLOCKCHAIN_DB DB_LMDB)
-
+
# temporarily allow mingw to compile with berkeley_db,
# regardless if building static or not
if(NOT STATIC OR MINGW)
- find_package(BerkeleyDB)
-
- if(NOT BERKELEY_DB_LIBRARIES)
- message(STATUS "BerkeleyDB not found and has been disabled.")
- else()
- message(STATUS "Found BerkeleyDB include (db.h) in ${BERKELEY_DB_INCLUDE_DIR}")
- if(BERKELEY_DB_LIBRARIES)
- message(STATUS "Found BerkeleyDB shared library")
- set(BDB_STATIC false CACHE BOOL "BDB Static flag")
- set(BDB_INCLUDE ${BERKELEY_DB_INCLUDE_DIR} CACHE STRING "BDB include path")
- set(BDB_LIBRARY ${BERKELEY_DB_LIBRARIES} CACHE STRING "BDB library name")
- set(BDB_LIBRARY_DIRS "" CACHE STRING "BDB Library dirs")
- set(BERKELEY_DB 1)
- else()
- message(STATUS "Found BerkeleyDB includes, but could not find BerkeleyDB library. Please make sure you have installed libdb and libdb-dev or the equivalent")
- endif()
- endif()
+ find_package(BerkeleyDB)
+
+ if(NOT BERKELEY_DB_LIBRARIES)
+ message(STATUS "BerkeleyDB not found and has been disabled.")
+ else()
+ message(STATUS "Found BerkeleyDB include (db.h) in ${BERKELEY_DB_INCLUDE_DIR}")
+ if(BERKELEY_DB_LIBRARIES)
+ message(STATUS "Found BerkeleyDB shared library")
+ set(BDB_STATIC false CACHE BOOL "BDB Static flag")
+ set(BDB_INCLUDE ${BERKELEY_DB_INCLUDE_DIR} CACHE STRING "BDB include path")
+ set(BDB_LIBRARY ${BERKELEY_DB_LIBRARIES} CACHE STRING "BDB library name")
+ set(BDB_LIBRARY_DIRS "" CACHE STRING "BDB Library dirs")
+ set(BERKELEY_DB 1)
+ else()
+ message(STATUS "Found BerkeleyDB includes, but could not find BerkeleyDB library. Please make sure you have installed libdb and libdb-dev or the equivalent")
+ endif()
+ endif()
endif()
if (BERKELEY_DB AND (ARCH_WIDTH STREQUAL "32" OR ARM6 OR ARM7))
@@ -234,7 +234,7 @@ endif()
if(BERKELEY_DB)
add_definitions("-DBERKELEY_DB")
endif()
-
+
add_definitions("-DBLOCKCHAIN_DB=${BLOCKCHAIN_DB}")
if (UNIX AND NOT APPLE)
@@ -309,6 +309,7 @@ else()
include_directories(SYSTEM src/platform/mingw)
# mingw doesn't support LTO (multiple definition errors at link time)
set(USE_LTO_DEFAULT false)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,10485760")
endif()
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wold-style-definition -Wstrict-prototypes")
set(CXX_WARNINGS "-Wno-reorder -Wno-missing-field-initializers")
diff --git a/README.md b/README.md
index c34e0d36c..32485cc7a 100644
--- a/README.md
+++ b/README.md
@@ -174,6 +174,12 @@ See README.i18n
## Using Tor
-While Monero isn't made to integrate with Tor, it can be used wrapped with torsocks, if you add --p2p-bind-ip 127.0.0.1 to the bitmonerod command line.
-Be aware that your DNS use will probably go over clearnet. These come in two flavours: request for checkpoint data, and request for OpenAlias data. The first one is mostly harmless (your ISP can tell you're using monero). The second one leaks information about your transaction recipients, so do not use OpenAlias if you want DNS privacy.
+While Monero isn't made to integrate with Tor, it can be used wrapped with torsocks, if you add --p2p-bind-ip 127.0.0.1 to the bitmonerod command line. You also want to set DNS requests to go over TCP, so they'll be routed through Tor, by setting DNS_PUBLIC=tcp. Example:
+
+DNS_PUBLIC=tcp torsocks bitmonerod --p2p-bind-ip 127.0.0.1
+
+## Using readline
+
+While bitmonerod and simplewallet do not use readline directly, most of the functionality can be obtained by running them via rlwrap. This allows command recall, edit capabilities, etc. It does not give autocompletion without an extra completion file, however. To use rlwrap, simply prepend "rlwrap " to the command line, eg:
+rlwrap bin/simplewallet --wallet-file /path/to/wallet
diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h
index 2adac7f2f..b4ba4b7e8 100644
--- a/contrib/epee/include/misc_log_ex.h
+++ b/contrib/epee/include/misc_log_ex.h
@@ -1316,52 +1316,52 @@ POP_WARNINGS
#if defined(ENABLE_LOGGING_INTERNAL)
-#define LOG_PRINT_NO_PREFIX2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
- {std::stringstream ss________; ss________ << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str() , y, epee::log_space::console_color_default, false, log_name);}}
+#define LOG_PRINT_NO_PREFIX2(log_name, x, y) do {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
+ {std::stringstream ss________; ss________ << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str() , y, epee::log_space::console_color_default, false, log_name);}} while(0)
-#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
- {std::stringstream ss________; ss________ << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}}
+#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) do {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
+ {std::stringstream ss________; ss________ << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}} while(0)
-#define LOG_PRINT_NO_POSTFIX2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
- {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}}
+#define LOG_PRINT_NO_POSTFIX2(log_name, x, y) do {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
+ {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}} while(0)
-#define LOG_PRINT2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
- {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}}
+#define LOG_PRINT2(log_name, x, y) do {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
+ {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}} while(0)
-#define LOG_PRINT_COLOR2(log_name, x, y, color) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
- {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name);}}
+#define LOG_PRINT_COLOR2(log_name, x, y, color) do {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
+ {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name);}} while(0)
-#define LOG_PRINT2_JORNAL(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
- {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);}}
+#define LOG_PRINT2_JORNAL(log_name, x, y) do {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\
+ {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);}} while(0)
-#define LOG_ERROR2(log_name, x) { \
- std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "ERROR " << __FILE__ << ":" << __LINE__ << " " << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name);LOCAL_ASSERT(0); epee::log_space::log_singletone::get_set_err_count(true, epee::log_space::log_singletone::get_set_err_count()+1);}
+#define LOG_ERROR2(log_name, x) do { \
+ std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "ERROR " << __FILE__ << ":" << __LINE__ << " " << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name);LOCAL_ASSERT(0); epee::log_space::log_singletone::get_set_err_count(true, epee::log_space::log_singletone::get_set_err_count()+1);} while(0)
#define LOG_FRAME2(log_name, x, y) epee::log_space::log_frame frame(x, y, log_name)
#else
-#define LOG_PRINT_NO_PREFIX2(log_name, x, y)
+#define LOG_PRINT_NO_PREFIX2(log_name, x, y) ((void)0)
-#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y)
+#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) ((void)0)
-#define LOG_PRINT_NO_POSTFIX2(log_name, x, y)
+#define LOG_PRINT_NO_POSTFIX2(log_name, x, y) ((void)0)
-#define LOG_PRINT_COLOR2(log_name, x, y, color)
+#define LOG_PRINT_COLOR2(log_name, x, y, color) ((void)0)
-#define LOG_PRINT2_JORNAL(log_name, x, y)
+#define LOG_PRINT2_JORNAL(log_name, x, y) ((void)0)
-#define LOG_PRINT2(log_name, x, y)
+#define LOG_PRINT2(log_name, x, y) ((void)0)
-#define LOG_ERROR2(log_name, x)
+#define LOG_ERROR2(log_name, x) ((void)0)
-#define LOG_FRAME2(log_name, x, y)
+#define LOG_FRAME2(log_name, x, y) ((void)0)
#endif
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.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp
index 07cb622a7..236bc4fe6 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.cpp
+++ b/src/blockchain_db/berkeleydb/db_bdb.cpp
@@ -2176,7 +2176,7 @@ uint8_t BlockchainBDB::get_hard_fork_version(uint64_t height) const
void BlockchainBDB::checkpoint_worker() const
{
- LOG_PRINT_L0("Entering BDB checkpoint thread.")
+ LOG_PRINT_L0("Entering BDB checkpoint thread.");
int count = 0;
while(m_run_checkpoint && m_open)
{
@@ -2188,12 +2188,12 @@ void BlockchainBDB::checkpoint_worker() const
count = 0;
if(m_env->txn_checkpoint(0, 0, 0) != 0)
{
- LOG_PRINT_L0("BDB txn_checkpoint failed.")
+ LOG_PRINT_L0("BDB txn_checkpoint failed.");
break;
}
}
}
- LOG_PRINT_L0("Leaving BDB checkpoint thread.")
+ LOG_PRINT_L0("Leaving BDB checkpoint thread.");
}
void BlockchainBDB::fixup()
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/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index f20e051f3..98480f247 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -515,7 +515,7 @@ int import_from_file(FakeCore& simple_core, const std::string& import_file_path,
#if !defined(BLOCKCHAIN_DB) || (BLOCKCHAIN_DB == DB_LMDB)
simple_core.m_storage.get_db().show_stats();
#endif
- LOG_PRINT_L0("Number of blocks imported: " << num_imported)
+ LOG_PRINT_L0("Number of blocks imported: " << num_imported);
if (h > 0)
// TODO: if there was an error, the last added block is probably at zero-based height h-2
LOG_PRINT_L0("Finished at block: " << h-1 << " total blocks: " << h);
diff --git a/src/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp
index d66d2f604..4a9d722e0 100644
--- a/src/blockchain_utilities/bootstrap_file.cpp
+++ b/src/blockchain_utilities/bootstrap_file.cpp
@@ -397,7 +397,7 @@ uint64_t BootstrapFile::seek_to_first_chunk(std::ifstream& import_file)
throw std::runtime_error("Error in deserialization of bootstrap::file_info");
LOG_PRINT_L0("bootstrap file v" << unsigned(bfi.major_version) << "." << unsigned(bfi.minor_version));
LOG_PRINT_L0("bootstrap magic size: " << sizeof(file_magic));
- LOG_PRINT_L0("bootstrap header size: " << bfi.header_size)
+ LOG_PRINT_L0("bootstrap header size: " << bfi.header_size);
uint64_t full_header_size = sizeof(file_magic) + bfi.header_size;
import_file.seekg(full_header_size);
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/common/scoped_message_writer.h b/src/common/scoped_message_writer.h
index 77ba56200..c4d430c5e 100644
--- a/src/common/scoped_message_writer.h
+++ b/src/common/scoped_message_writer.h
@@ -88,7 +88,7 @@ public:
{
m_flush = false;
- LOG_PRINT(m_oss.str(), m_log_level)
+ LOG_PRINT(m_oss.str(), m_log_level);
if (epee::log_space::console_color_default == m_color)
{
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..badccd06f 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::unique_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
+bool Blockchain::get_hard_fork_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, 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, earliest_height, 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..1efc4e394 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,16 +153,16 @@ 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(); }
uint8_t get_ideal_hard_fork_version(uint64_t height) const { return m_hardfork->get_ideal_version(height); }
- bool get_hard_fork_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint8_t &voting) const;
+ bool get_hard_fork_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const;
bool for_all_key_images(std::function<bool(const crypto::key_image&)>) const;
bool for_all_blocks(std::function<bool(uint64_t, const crypto::hash&, const block&)>) const;
@@ -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/hardfork.cpp b/src/cryptonote_core/hardfork.cpp
index 550047289..9bd4a337c 100644
--- a/src/cryptonote_core/hardfork.cpp
+++ b/src/cryptonote_core/hardfork.cpp
@@ -355,7 +355,16 @@ uint8_t HardFork::get_ideal_version(uint64_t height) const
return original_version;
}
-bool HardFork::get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint8_t &voting) const
+uint64_t HardFork::get_earliest_ideal_height_for_version(uint8_t version) const
+{
+ for (unsigned int n = heights.size() - 1; n > 0; --n) {
+ if (heights[n].version <= version)
+ return heights[n].height;
+ }
+ return 0;
+}
+
+bool HardFork::get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
{
CRITICAL_REGION_LOCAL(lock);
@@ -367,6 +376,7 @@ bool HardFork::get_voting_info(uint8_t version, uint32_t &window, uint32_t &vote
votes += last_versions[n];
threshold = (window * heights[current_version].threshold + 99) / 100;
assert((votes >= threshold) == enabled);
+ earliest_height = get_earliest_ideal_height_for_version(version);
voting = heights.back().version;
return enabled;
}
diff --git a/src/cryptonote_core/hardfork.h b/src/cryptonote_core/hardfork.h
index 6d2a3c55b..d2f701799 100644
--- a/src/cryptonote_core/hardfork.h
+++ b/src/cryptonote_core/hardfork.h
@@ -184,6 +184,11 @@ namespace cryptonote
uint8_t get_current_version() const;
/**
+ * @brief returns the earliest block a given version may activate
+ */
+ uint64_t get_earliest_ideal_height_for_version(uint8_t version) const;
+
+ /**
* @brief returns information about current voting state
*
* returns true if the given version is enabled (ie, the current version
@@ -193,8 +198,9 @@ namespace cryptonote
* @param window the number of blocks considered in voting
* @param votes number of votes for next version
* @param threshold number of votes needed to switch to next version
+ * @param earliest_height earliest height at which the version can take effect
*/
- bool get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint8_t &voting) const;
+ bool get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const;
/**
* @brief returns the size of the voting window in blocks
diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp
index b99113d9e..00a474524 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;
@@ -257,7 +257,7 @@ namespace cryptonote
m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this)));
}
- LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" )
+ LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" );
return true;
}
//-----------------------------------------------------------------------------------------------------
@@ -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-base.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp
index 12ec4b14a..e5340d62f 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp
@@ -123,7 +123,7 @@ cryptonote_protocol_handler_base::~cryptonote_protocol_handler_base() {
void cryptonote_protocol_handler_base::handler_request_blocks_history(std::list<crypto::hash>& ids) {
using namespace epee::net_utils;
LOG_PRINT_L1("### ~~~RRRR~~~~ ### sending request (type 2), limit = " << ids.size());
- LOG_PRINT_RED("RATE LIMIT NOT IMPLEMENTED HERE YET (download at unlimited speed?)" , LOG_LEVEL_0);
+ LOG_PRINT_RED("RATE LIMIT NOT IMPLEMENTED HERE YET (download at unlimited speed?)" , LOG_LEVEL_1);
_note_c("net/req2", "### ~~~RRRR~~~~ ### sending request (type 2), limit = " << ids.size());
// TODO
}
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 1de55a685..149af595d 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
@@ -50,8 +50,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();
@@ -76,7 +76,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());
@@ -131,7 +131,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);
@@ -260,7 +260,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/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 686af69c2..9e7f3fdc3 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -241,6 +241,7 @@ bool t_rpc_command_executor::show_difficulty() {
}
tools::success_msg_writer() << "BH: " << res.height
+ << ", TH: " << res.top_block_hash
<< ", DIFF: " << res.difficulty
<< ", HR: " << (int) res.difficulty / res.target << " H/s";
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 aa22d5b23..254c9ae72 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);
@@ -182,7 +182,7 @@ namespace nodetool
if(time(nullptr) >= it->second)
{
m_blocked_ips.erase(it);
- LOG_PRINT_CYAN("IP " << epee::string_tools::get_ip_string_from_int32(addr) << "is unblocked.", LOG_LEVEL_0);
+ LOG_PRINT_CYAN("IP " << epee::string_tools::get_ip_string_from_int32(addr) << " unblocked.", LOG_LEVEL_0);
return true;
}
return false;
@@ -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());
@@ -380,7 +380,7 @@ namespace nodetool
{
boost::thread* th = new boost::thread([=, &dns_results, &addr_str]
{
- LOG_PRINT_L4("dns_threads[" << result_index << "] created for: " << addr_str)
+ LOG_PRINT_L4("dns_threads[" << result_index << "] created for: " << addr_str);
// TODO: care about dnssec avail/valid
bool avail, valid;
std::vector<std::string> addr_list;
@@ -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/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index b566e7318..57d3b0d0b 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -117,7 +117,14 @@ namespace cryptonote
bool core_rpc_server::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res)
{
CHECK_CORE_BUSY();
- res.height = m_core.get_current_blockchain_height();
+ crypto::hash top_hash;
+ if (!m_core.get_blockchain_top(res.height, top_hash))
+ {
+ res.status = "Failed";
+ return false;
+ }
+ ++res.height; // turn top block height into blockchain height
+ res.top_block_hash = string_tools::pod_to_hex(top_hash);
res.target_height = m_core.get_target_blockchain_height();
res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block();
res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET;
@@ -890,7 +897,7 @@ namespace cryptonote
const Blockchain &blockchain = m_core.get_blockchain_storage();
uint8_t version = req.version > 0 ? req.version : blockchain.get_ideal_hard_fork_version();
res.version = blockchain.get_current_hard_fork_version();
- res.enabled = blockchain.get_hard_fork_voting_info(version, res.window, res.votes, res.threshold, res.voting);
+ res.enabled = blockchain.get_hard_fork_voting_info(version, res.window, res.votes, res.threshold, res.earliest_height, res.voting);
res.state = blockchain.get_hard_fork_state();
res.status = CORE_RPC_STATUS_OK;
return true;
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index b70164614..5ad4450d4 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -282,6 +282,7 @@ namespace cryptonote
uint64_t white_peerlist_size;
uint64_t grey_peerlist_size;
bool testnet;
+ std::string top_block_hash;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -296,6 +297,7 @@ namespace cryptonote
KV_SERIALIZE(white_peerlist_size)
KV_SERIALIZE(grey_peerlist_size)
KV_SERIALIZE(testnet)
+ KV_SERIALIZE(top_block_hash)
END_KV_SERIALIZE_MAP()
};
};
@@ -875,6 +877,7 @@ namespace cryptonote
uint32_t threshold;
uint8_t voting;
uint32_t state;
+ uint64_t earliest_height;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
@@ -885,6 +888,7 @@ namespace cryptonote
KV_SERIALIZE(threshold)
KV_SERIALIZE(voting)
KV_SERIALIZE(state)
+ KV_SERIALIZE(earliest_height)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index d1ff09170..ad4cd5622 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -157,7 +157,7 @@ namespace
{
m_flush = false;
- LOG_PRINT(m_oss.str(), m_log_level)
+ LOG_PRINT(m_oss.str(), m_log_level);
if (epee::log_space::console_color_default == m_color)
{
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 5a9b96bb8..d10529194 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"
@@ -228,7 +229,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_
// process the other outs from that tx
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));
+ std::unique_ptr < boost::asio::io_service::work > work(new boost::asio::io_service::work(ioservice));
for (int i = 0; i < threads; i++)
{
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
@@ -264,7 +265,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_
{
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));
+ std::unique_ptr < boost::asio::io_service::work > work(new boost::asio::io_service::work(ioservice));
for (int i = 0; i < threads; i++)
{
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
@@ -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
@@ -2326,9 +2339,44 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n
}
//----------------------------------------------------------------------------------------------------
+bool wallet2::use_fork_rules(uint8_t version)
+{
+ cryptonote::COMMAND_RPC_GET_HEIGHT::request req = AUTO_VAL_INIT(req);
+ cryptonote::COMMAND_RPC_GET_HEIGHT::response res = AUTO_VAL_INIT(res);
+ epee::json_rpc::request<cryptonote::COMMAND_RPC_HARD_FORK_INFO::request> req_t = AUTO_VAL_INIT(req_t);
+ epee::json_rpc::response<cryptonote::COMMAND_RPC_HARD_FORK_INFO::response, std::string> resp_t = AUTO_VAL_INIT(resp_t);
+
+ m_daemon_rpc_mutex.lock();
+ bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client);
+ m_daemon_rpc_mutex.unlock();
+ CHECK_AND_ASSERT_MES(r, false, "Failed to connect to daemon");
+ CHECK_AND_ASSERT_MES(res.status != CORE_RPC_STATUS_BUSY, false, "Failed to connect to daemon");
+ CHECK_AND_ASSERT_MES(res.status == CORE_RPC_STATUS_OK, false, "Failed to get current blockchain height");
+
+ m_daemon_rpc_mutex.lock();
+ req_t.jsonrpc = "2.0";
+ req_t.id = epee::serialization::storage_entry(0);
+ req_t.method = "hard_fork_info";
+ req_t.params.version = version;
+ r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ m_daemon_rpc_mutex.unlock();
+ CHECK_AND_ASSERT_MES(r, false, "Failed to connect to daemon");
+ CHECK_AND_ASSERT_MES(res.status != CORE_RPC_STATUS_BUSY, false, "Failed to connect to daemon");
+ CHECK_AND_ASSERT_MES(res.status == CORE_RPC_STATUS_OK, false, "Failed to get hard fork status");
+
+ bool close_enough = res.height >= resp_t.result.earliest_height - 10; // start using the rules a bit beforehand
+ if (close_enough)
+ LOG_PRINT_L2("Using HF1 rules");
+ else
+ LOG_PRINT_L2("Not using HF1 rules");
+ return close_enough;
+}
+//----------------------------------------------------------------------------------------------------
std::vector<wallet2::pending_tx> wallet2::create_dust_sweep_transactions()
{
- tx_dust_policy dust_policy(::config::DEFAULT_DUST_THRESHOLD);
+ // From hard fork 1, we don't consider small amounts to be dust anymore
+ const bool hf1_rules = use_fork_rules(2); // first hard fork has version 2
+ tx_dust_policy dust_policy(hf1_rules ? 0 : ::config::DEFAULT_DUST_THRESHOLD);
size_t num_dust_outputs = 0;
for (transfer_container::const_iterator i = m_transfers.begin(); i != m_transfers.end(); ++i)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index ecf4ef3dc..adb7b13e2 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -372,6 +372,7 @@ namespace tools
crypto::hash get_payment_id(const pending_tx &ptx) const;
void check_acc_out(const cryptonote::account_keys &acc, const cryptonote::tx_out &o, const crypto::public_key &tx_pub_key, size_t i, uint64_t &money_transfered, bool &error) const;
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
+ bool use_fork_rules(uint8_t version);
cryptonote::account_base m_account;
std::string m_daemon_address;
@@ -408,6 +409,9 @@ namespace tools
};
}
BOOST_CLASS_VERSION(tools::wallet2, 10)
+BOOST_CLASS_VERSION(tools::wallet2::payment_details, 0)
+BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 1)
+BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 1)
namespace boost
{
@@ -430,7 +434,7 @@ namespace boost
a & x.m_change;
a & x.m_sent_time;
a & x.m_tx;
- if (ver < 9)
+ if (ver < 1)
return;
a & x.m_dests;
a & x.m_payment_id;
@@ -443,7 +447,7 @@ namespace boost
a & x.m_amount_out;
a & x.m_change;
a & x.m_block_height;
- if (ver < 9)
+ if (ver < 1)
return;
a & x.m_dests;
a & x.m_payment_id;
@@ -552,7 +556,8 @@ namespace tools
// randomly select inputs for transaction
// throw if requested send amount is greater than amount available to send
std::list<transfer_container::iterator> selected_transfers;
- uint64_t found_money = select_transfers(needed_money, 0 == fake_outputs_count, dust_policy.dust_threshold, selected_transfers);
+ const bool add_dust = (0 == fake_outputs_count) && !use_fork_rules(2); // first fork has version 2
+ uint64_t found_money = select_transfers(needed_money, add_dust, dust_policy.dust_threshold, selected_transfers);
THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_money, found_money, needed_money - fee, fee);
typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry;
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(); }