1
0
Fork 0
forked from lthn/blockchain

Merge branch 'master' into frontend

This commit is contained in:
wildkif 2019-02-19 09:51:45 +02:00
commit ac5ab57337
38 changed files with 1176 additions and 529 deletions

View file

@ -45,6 +45,10 @@ if (UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
endif()
# TODO(unassigned): expand on types and versions, and then refactor.
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CLANG TRUE)
endif()
if(MSVC)
add_definitions("/bigobj /Zm1000 /Z7 /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4503 /wd4345 /wd4091 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__")
@ -66,7 +70,6 @@ else()
# if(NOT APPLE)
# set(WARNINGS "${WARNINGS} -Werror")
# endif()
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(WARNINGS "${WARNINGS} -Wno-shift-count-overflow -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration")
else()
@ -103,13 +106,15 @@ else()
else()
set(STATIC_ASSERT_FLAG "-Dstatic_assert=_Static_assert")
endif()
set(LINUX_LD_GOLD "")
set(LINUX_STATIC_ICU "")
if((NOT APPLE) AND (NOT MSVC))
set(LINUX_LD_GOLD "-fuse-ld=gold")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -ftemplate-depth-1024 -std=c++11 -D_GNU_SOURCE ${APPLE_FLAG} ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
if (NOT APPLE AND NOT MSVC)
if (CLANG)
set(LLVM_USE_LINKER "gold")
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
endif()
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LINUX_LD_GOLD} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LINUX_LD_GOLD} -fpermissive -ftemplate-depth-1024 -std=c++11 -D_GNU_SOURCE ${APPLE_FLAG} ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8))
set(DEBUG_FLAGS "-g3 -O0") #set(DEBUG_FLAGS "-g3 -Og")
else()

View file

@ -4,7 +4,8 @@ Building
### Dependencies
| component / version | minimum <br>(not recommended but may work) | recommended | most recent of what we have ever tested |
|--|--|--|--|
| gcc (Linux) | 5.4.0 | 7.2.0 | 7.2.0 |
| gcc (Linux) | 5.4.0 | 7.2.0 | 8.2.1 |
| llvm/clang (Linux) | UNKNOWN | 7.0.1 | 7.0.1 |
| [MSVC](https://visualstudio.microsoft.com/downloads/) (Windows) | 2015 (14.0 update 1) | 2015 (14.0 update 3) | 2017 (15.5.7) |
| [XCode](https://developer.apple.com/downloads/) (macOS) | 7.3.1 | 9.2 | 9.2 |
| [CMake](https://cmake.org/download/) | 2.8.6 | 3.4.1 | 3.11.0 |

View file

@ -2,6 +2,6 @@ add_subdirectory(liblmdb)
if(MSVC)
target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172)
else()
target_compile_options(lmdb PRIVATE -Wno-discarded-qualifiers -Wno-empty-body -Wno-unused-but-set-variable)
# Warnings as used by LMDB itself (LMDB_0.9.23)
target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized)
endif()

View file

@ -35,12 +35,11 @@ namespace eos {
// version of the linked boost archive library
const archive_version_type archive_version(
11
// #if BOOST_VERSION < 103700
// boost::archive::ARCHIVE_VERSION()
// #else
// boost::archive::BOOST_ARCHIVE_VERSION()
// #endif
#if BOOST_VERSION < 103700
boost::archive::ARCHIVE_VERSION()
#else
boost::archive::BOOST_ARCHIVE_VERSION()
#endif
);
/**

View file

@ -3,7 +3,7 @@
* \file portable_iarchive.hpp
* \brief Provides an archive to read from portable binary files.
* \author christian.pfligersdorffer@gmx.at
* \version 5.0
* \version 5.1
*
* This pair of archives brings the advantages of binary streams to the cross
* platform boost::serialization user. While being almost as fast as the native
@ -23,6 +23,9 @@
* chance it will instantly work for your specific setup. If you encounter
* problems or have suggestions please contact the author.
*
* \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to
* ecotax for pointing to the issue with shared_ptr_helper.
*
* \note Version 5.0 is now compatible with boost up to version 1.49 and enables
* serialization of std::wstring by converting it to/from utf8 (thanks to
* Arash Abghari for this suggestion). With that all unit tests from the
@ -89,9 +92,7 @@
#include <boost/archive/basic_binary_iprimitive.hpp>
#include <boost/archive/basic_binary_iarchive.hpp>
#if BOOST_VERSION >= 105600
#include <boost/serialization/shared_ptr_helper.hpp>
#elif BOOST_VERSION >= 103500
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
#include <boost/archive/shared_ptr_helper.hpp>
#endif
@ -115,14 +116,15 @@
#include <boost/math/fpclassify.hpp>
#elif BOOST_VERSION < 104800
#include <boost/spirit/home/support/detail/integer/endian.hpp>
// Boost 1.69 (Spirit.X2/X3) has dropped their own FP routines in favor of boost::math
#elif BOOST_VERSION < 106900
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
#else
#include <boost/spirit/home/support/detail/endian/endian.hpp>
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
#endif
// namespace alias
#if BOOST_VERSION < 103800
#if BOOST_VERSION < 103800 || BOOST_VERSION >= 106900
namespace fp = boost::math;
#else
namespace fp = boost::spirit::math;
@ -135,7 +137,7 @@ namespace endian = boost::detail;
namespace endian = boost::spirit::detail;
#endif
#ifndef BOOST_NO_STD_WSTRING
#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING
// used for wstring to utf8 conversion
#include <boost/program_options/config.hpp>
#include <boost/program_options/detail/convert.hpp>
@ -190,9 +192,7 @@ namespace eos {
// load_override functions so we chose to stay one level higher
, public boost::archive::basic_binary_iarchive<portable_iarchive>
#if BOOST_VERSION >= 105600
// mix-in helper class for serializing shared_ptr does not exist anymore
#elif BOOST_VERSION >= 103500
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
// mix-in helper class for serializing shared_ptr
, public boost::archive::detail::shared_ptr_helper
#endif
@ -349,7 +349,7 @@ namespace eos {
T temp = size < 0 ? -1 : 0;
load_binary(&temp, abs(size));
// load the value from little endian - is is then converted
// load the value from little endian - it is then converted
// to the target type T and fits it because size <= sizeof(T)
t = endian::load_little_endian<T, sizeof(T)>(&temp);
}

View file

@ -3,7 +3,7 @@
* \file portable_oarchive.hpp
* \brief Provides an archive to create portable binary files.
* \author christian.pfligersdorffer@gmx.at
* \version 5.0
* \version 5.1
*
* This pair of archives brings the advantages of binary streams to the cross
* platform boost::serialization user. While being almost as fast as the native
@ -23,6 +23,9 @@
* chance it will instantly work for your specific setup. If you encounter
* problems or have suggestions please contact the author.
*
* \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to
* ecotax for pointing to the issue with shared_ptr_helper.
*
* \note Version 5.0 is now compatible with boost up to version 1.49 and enables
* serialization of std::wstring by converting it to/from utf8 (thanks to
* Arash Abghari for this suggestion). With that all unit tests from the
@ -91,15 +94,9 @@
#include <boost/utility/enable_if.hpp>
#include <boost/archive/basic_binary_oprimitive.hpp>
#include <boost/archive/basic_binary_oarchive.hpp>
#if BOOST_VERSION >= 105600
#include <boost/serialization/shared_ptr_helper.hpp>
#elif BOOST_VERSION >= 103500
#include <boost/archive/shared_ptr_helper.hpp>
#endif
#if BOOST_VERSION >= 104500
#include <boost/program_options/config.hpp>
#include <boost/program_options/detail/convert.hpp>
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
#include <boost/archive/shared_ptr_helper.hpp>
#endif
// funny polymorphics
@ -122,14 +119,15 @@
#include <boost/math/fpclassify.hpp>
#elif BOOST_VERSION < 104800
#include <boost/spirit/home/support/detail/integer/endian.hpp>
// Boost 1.69 (Spirit.X2/X3) has dropped their own FP routines in favor of boost::math
#elif BOOST_VERSION < 106900
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
#else
#include <boost/spirit/home/support/detail/endian/endian.hpp>
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
#endif
// namespace alias fp_classify
#if BOOST_VERSION < 103800
#if BOOST_VERSION < 103800 || BOOST_VERSION >= 106900
namespace fp = boost::math;
#else
namespace fp = boost::spirit::math;
@ -142,7 +140,7 @@ namespace endian = boost::detail;
namespace endian = boost::spirit::detail;
#endif
#ifndef BOOST_NO_STD_WSTRING
#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING
// used for wstring to utf8 conversion
#include <boost/program_options/config.hpp>
#include <boost/program_options/detail/convert.hpp>
@ -195,9 +193,7 @@ namespace eos {
// save_override functions so we chose to stay one level higher
, public boost::archive::basic_binary_oarchive<portable_oarchive>
#if BOOST_VERSION >= 105600
// mix-in helper class for serializing shared_ptr does not exist anymore
#elif BOOST_VERSION >= 103500
#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600
// mix-in helper class for serializing shared_ptr
, public boost::archive::detail::shared_ptr_helper
#endif

View file

@ -893,12 +893,10 @@ namespace log_space
FAST_CRITICAL_REGION_END();
return true;
}
std::string get_thread_prefix()
{
FAST_CRITICAL_REGION_LOCAL(m_critical_sec);
return m_thr_prefix_strings[misc_utils::get_thread_string_id()];
}
std::string get_default_log_file()
@ -1160,7 +1158,6 @@ namespace log_space
}
static bool add_logger( ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4 )
{
logger* plogger = get_or_create_instance();
@ -1234,8 +1231,6 @@ POP_WARNINGS
}
#ifdef _MSC_VER
@ -1290,8 +1285,6 @@ POP_WARNINGS
return plogger->get_thread_prefix();
}
static std::string get_prefix_entry()
{
std::stringstream str_prefix;
@ -1587,8 +1580,6 @@ POP_WARNINGS
#endif
#define LOG_PRINT_NO_POSTFIX(mess, level) LOG_PRINT_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level)
#define LOG_PRINT_NO_PREFIX(mess, level) LOG_PRINT_NO_PREFIX2(LOG_DEFAULT_TARGET, mess, level)
#define LOG_PRINT_NO_PREFIX_NO_POSTFIX(mess, level) LOG_PRINT_NO_PREFIX_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level)
@ -1694,7 +1685,6 @@ POP_WARNINGS
#define CHECK_AND_ASSERT_MES2(expr, message) do{if(!(expr)) {LOG_ERROR(message); };}while(0)
#endif
}
POP_WARNINGS

View file

@ -137,6 +137,7 @@ namespace net_utils
bool m_is_stop_handling;
http::http_request_info m_query_info;
size_t m_len_summary, m_len_remain;
size_t m_precommand_line_chars;
config_type& m_config;
bool m_want_close;
protected:

View file

@ -33,8 +33,9 @@
#include "file_io_utils.h"
#include "net_parse_helpers.h"
#define HTTP_MAX_URI_LEN 9000
#define HTTP_MAX_HEADER_LEN 100000
#define HTTP_MAX_URI_LEN 9000
#define HTTP_MAX_PRE_COMMAND_LINE_CHARS 20
#define HTTP_MAX_HEADER_LEN 100000
PUSH_WARNINGS
DISABLE_GCC_WARNING(maybe-uninitialized)
@ -204,7 +205,8 @@ namespace net_utils
m_len_remain(0),
m_config(config),
m_want_close(false),
m_psnd_hndlr(psnd_hndlr)
m_psnd_hndlr(psnd_hndlr),
m_precommand_line_chars(0)
{
}
@ -217,6 +219,7 @@ namespace net_utils
m_body_transfer_type = http_body_transfer_undefined;
m_query_info.clear();
m_len_summary = 0;
m_precommand_line_chars = 0;
return true;
}
//--------------------------------------------------------------------------------------------
@ -257,11 +260,19 @@ namespace net_utils
if((m_cache[0] == '\r' || m_cache[0] == '\n'))
{
//some times it could be that before query line cold be few line breaks
//so we have to be calm without panic with assers
//so we have to be calm down without panic and asserts
m_cache.erase(0, 1);
//fixed bug with possible '\r\n' chars flood, thanks to @anonimal (https://github.com/anonimal) for pointing this
++m_precommand_line_chars;
if (m_precommand_line_chars > HTTP_MAX_PRE_COMMAND_LINE_CHARS)
{
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long URI line");
m_state = http_state_error;
return false;
}
break;
}
if(std::string::npos != m_cache.find('\n', 0))
handle_invoke_query_line();
else
@ -269,7 +280,7 @@ namespace net_utils
m_is_stop_handling = true;
if(m_cache.size() > HTTP_MAX_URI_LEN)
{
LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too long URI line");
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long URI line");
m_state = http_state_error;
return false;
}
@ -297,10 +308,10 @@ namespace net_utils
case http_state_connection_close:
return false;
default:
LOG_ERROR("simple_http_connection_handler::handle_char_out: Wrong state: " << m_state);
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Wrong state: " << m_state);
return false;
case http_state_error:
LOG_ERROR("simple_http_connection_handler::handle_char_out: Error state!!!");
LOG_ERROR("simple_http_connection_handler::handle_buff_in: Error state!!!");
return false;
}
@ -334,10 +345,10 @@ namespace net_utils
template<class t_connection_context>
bool simple_http_connection_handler<t_connection_context>::handle_invoke_query_line()
{
LOG_FRAME("simple_http_connection_handler<t_connection_context>::handle_recognize_protocol_out(*)", LOG_LEVEL_3);
LOG_FRAME("simple_http_connection_handler<t_connection_context>::handle_invoke_query_line(*)", LOG_LEVEL_3);
STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^(((OPTIONS)|(GET)|(HEAD)|(POST)|(PUT)|(DELETE)|(TRACE)) (\\S+) HTTP/(\\d+).(\\d+))\r?\n", boost::regex::icase | boost::regex::normal);
// 123 4 5 6 7 8 9 10 11 12
// 123 4 5 6 7 8 9 10 11 12
//size_t match_len = 0;
boost::smatch result;
if(boost::regex_search(m_cache, result, rexp_match_command_line, boost::match_default) && result[0].matched)
@ -682,4 +693,4 @@ namespace net_utils
POP_WARNINGS
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------

View file

@ -701,6 +701,11 @@ namespace epee
#define CRITICAL_REGION_BEGIN1(x) CRITICAL_REGION_BEGIN_VAR(x, critical_region_var1)
#define CRITICAL_REGION_END() }
#define SHARED_CRITICAL_REGION_LOCAL(x) boost::shared_lock< boost::shared_mutex > critical_region_var(x)
#define EXCLUSIVE_CRITICAL_REGION_LOCAL(x) boost::unique_lock< boost::shared_mutex > critical_region_var(x)
#define SHARED_CRITICAL_REGION_BEGIN(x) { SHARED_CRITICAL_REGION_LOCAL(x)
#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { EXCLUSIVE_CRITICAL_REGION_LOCAL(x)
}

View file

@ -92,7 +92,7 @@ add_library(common ${COMMON})
add_dependencies(common version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(COMMON)
if(NOT MSVC AND NOT APPLE)
if(NOT MSVC AND NOT APPLE AND NOT CLANG) # TODO(unassigned): do we really need the clang equivalent?
target_compile_options(common PRIVATE -fno-var-tracking-assignments)
endif()

View file

@ -0,0 +1,36 @@
// Copyright (c) 2018-2019 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <string>
#include <sstream>
#include "include_base_utils.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
//------
bool parse_hash256(const std::string str_hash, crypto::hash& hash);
template <class T>
std::ostream &print256(std::ostream &o, const T &v) {
return o << "<" << epee::string_tools::pod_to_hex(v) << ">";
}
template <class T>
std::ostream &print16(std::ostream &o, const T &v) {
return o << "<" << epee::string_tools::pod_to_hex(v).substr(0, 5) << "..>";
}
template <class T>
std::string print16(const T &v) {
return std::string("<") + epee::string_tools::pod_to_hex(v).substr(0, 5) + "..>";
}
namespace crypto {
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); }
}

View file

@ -34,11 +34,13 @@
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
#include <cassert>
#include <map>
#include <cstdint>
#include <boost/algorithm/string.hpp>
#include "mnemonic-encoding.h"
#include "include_base_utils.h"
namespace tools
{
@ -3371,5 +3373,18 @@ namespace tools
}
return res;
}
std::string word_by_num(uint32_t n)
{
if (n >= NUMWORDS)
return "";
return wordsArray[n];
}
uint64_t num_by_word(const std::string& w)
{
auto it = wordsMap.find(w);
CHECK_AND_ASSERT_THROW_MES(it!= wordsMap.end(), "unable to find word \"" << w << "\" in mnemonic dictionary");
return it->second;
}
}
}

View file

@ -42,5 +42,7 @@ namespace tools
{
std::vector<unsigned char> text2binary(const std::string& text);
std::string binary2text(const std::vector<unsigned char>& binary);
std::string word_by_num(uint32_t n);
uint64_t num_by_word(const std::string& w);
}
}

View file

@ -5,6 +5,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "include_base_utils.h"
#include "zlib_helper.h"
using namespace epee;
#include "util.h"
@ -526,4 +527,65 @@ std::string get_nix_version_display_string()
#endif
return std::error_code(code, std::system_category());
}
#define REQUEST_LOG_CHUNK_SIZE_MAX (10 * 1024 * 1024)
bool get_log_chunk_gzipped(uint64_t offset, uint64_t size, std::string& output, std::string& error)
{
if (size > REQUEST_LOG_CHUNK_SIZE_MAX)
{
error = std::string("size is exceeding the limit = ") + epee::string_tools::num_to_string_fast(REQUEST_LOG_CHUNK_SIZE_MAX);
return false;
}
std::string log_filename = epee::log_space::log_singletone::get_actual_log_file_path();
if (std::ifstream log{ log_filename, std::ifstream::ate | std::ifstream::binary })
{
uint64_t file_size = log.tellg();
if (offset >= file_size)
{
error = "offset is out of bounds";
return false;
}
if (offset + size > file_size)
{
error = "offset + size if out of bounds";
return false;
}
if (size != 0)
{
log.seekg(offset);
output.resize(size);
log.read(&output.front(), size);
uint64_t read_bytes = log.gcount();
if (read_bytes != size)
{
error = std::string("read bytes: ") + epee::string_tools::num_to_string_fast(read_bytes);
return false;
}
if (!epee::zlib_helper::pack(output))
{
error = "zlib pack failed";
return false;
}
}
return true;
}
error = std::string("can't open ") + log_filename;
return false;
}
uint64_t get_log_file_size()
{
std::string log_filename = epee::log_space::log_singletone::get_actual_log_file_path();
std::ifstream in(log_filename, std::ifstream::ate | std::ifstream::binary);
return static_cast<uint64_t>(in.tellg());
}
}

View file

@ -48,6 +48,8 @@ namespace tools
return k;
}
bool get_log_chunk_gzipped(uint64_t offset, uint64_t size, std::string& output, std::string& error);
uint64_t get_log_file_size();
class signal_handler
{

View file

@ -54,6 +54,8 @@ namespace
const command_line::arg_descriptor<std::string> arg_generate_genesis = {"generate-genesis", "Generate genesis coinbase based on config file", "", true };
const command_line::arg_descriptor<uint64_t> arg_genesis_split_amount = { "genesis-split-amount", "Set split amount for generating genesis block", 0, true };
const command_line::arg_descriptor<std::string> arg_get_info_flags = { "getinfo-flags-hex", "Set of bits for rpc-get-daemon-info", "", true };
const command_line::arg_descriptor<int64_t> arg_set_peer_log_level = { "set-peer-log-level", "Set log level for remote peer", 0, true };
const command_line::arg_descriptor<uint64_t> arg_download_peer_log = { "download-peer-log", "Download log from remote peer (starting offset)", 0, true };
}
typedef COMMAND_REQUEST_STAT_INFO_T<t_currency_protocol_handler<core>::stat_info> COMMAND_REQUEST_STAT_INFO;
@ -839,7 +841,166 @@ bool generate_and_print_keys()
<< "PRIVATE KEY: " << epee::string_tools::pod_to_hex(sk);
return true;
}
//---------------------------------------------------------------------------------------------------------------
template<class command_t>
bool invoke_debug_command(po::variables_map& vm, const crypto::secret_key& sk, levin::levin_client_impl2& transport, peerid_type& peer_id, typename command_t::request& req, typename command_t::response& rsp)
{
if (!transport.is_connected())
{
if (!transport.connect(command_line::get_arg(vm, arg_ip), static_cast<int>(command_line::get_arg(vm, arg_port)), static_cast<int>(command_line::get_arg(vm, arg_timeout))))
{
std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "Failed to connect to " << command_line::get_arg(vm, arg_ip) << ":" << command_line::get_arg(vm, arg_port) << "\"" << ENDL << "}" << ENDL;
return false;
}
}
if (!peer_id)
{
COMMAND_REQUEST_PEER_ID::request id_req = AUTO_VAL_INIT(id_req);
COMMAND_REQUEST_PEER_ID::response id_rsp = AUTO_VAL_INIT(id_rsp);
if (!net_utils::invoke_remote_command2(COMMAND_REQUEST_PEER_ID::ID, id_req, id_rsp, transport))
{
std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "Failed to connect to " << command_line::get_arg(vm, arg_ip) << ":" << command_line::get_arg(vm, arg_port) << "\"" << ENDL << "}" << ENDL;
return false;
}
else
{
peer_id = id_rsp.my_id;
}
}
nodetool::proof_of_trust pot = AUTO_VAL_INIT(pot);
pot.peer_id = peer_id;
pot.time = time(NULL);
crypto::public_key pubk = AUTO_VAL_INIT(pubk);
string_tools::hex_to_pod(P2P_MAINTAINERS_PUB_KEY, pubk);
crypto::hash h = tools::get_proof_of_trust_hash(pot);
crypto::generate_signature(h, pubk, sk, pot.sign);
req.tr = pot;
return net_utils::invoke_remote_command2(command_t::ID, req, rsp, transport);
}
//---------------------------------------------------------------------------------------------------------------
bool handle_set_peer_log_level(po::variables_map& vm)
{
crypto::secret_key sk = AUTO_VAL_INIT(sk);
if (!get_private_key(sk, vm))
{
std::cout << "ERROR: secret key error" << ENDL;
return false;
}
int64_t log_level = command_line::get_arg(vm, arg_set_peer_log_level);
if (log_level < LOG_LEVEL_0 || log_level > LOG_LEVEL_MAX)
{
std::cout << "Error: invalid log level value: " << log_level << ENDL;
return false;
}
levin::levin_client_impl2 transport;
peerid_type peer_id = 0;
COMMAND_SET_LOG_LEVEL::request req = AUTO_VAL_INIT(req);
req.new_log_level = log_level;
COMMAND_SET_LOG_LEVEL::response rsp = AUTO_VAL_INIT(rsp);
if (!invoke_debug_command<COMMAND_SET_LOG_LEVEL>(vm, sk, transport, peer_id, req, rsp))
{
std::cout << "ERROR: invoking COMMAND_SET_LOG_LEVEL failed" << ENDL;
return false;
}
std::cout << "OK! Log level changed: " << rsp.old_log_level << " -> " << rsp.current_log_level << ENDL;
return true;
}
//---------------------------------------------------------------------------------------------------------------
bool handle_download_peer_log(po::variables_map& vm)
{
crypto::secret_key sk = AUTO_VAL_INIT(sk);
if (!get_private_key(sk, vm))
{
std::cout << "ERROR: secret key error" << ENDL;
return false;
}
uint64_t start_offset = command_line::get_arg(vm, arg_download_peer_log);
levin::levin_client_impl2 transport;
peerid_type peer_id = 0;
COMMAND_REQUEST_LOG::request req = AUTO_VAL_INIT(req);
COMMAND_REQUEST_LOG::response rsp = AUTO_VAL_INIT(rsp);
if (!invoke_debug_command<COMMAND_REQUEST_LOG>(vm, sk, transport, peer_id, req, rsp) || !rsp.error.empty())
{
std::cout << "ERROR: invoking COMMAND_REQUEST_LOG failed: " << rsp.error << ENDL;
return false;
}
std::cout << "Current log level: " << rsp.current_log_level << ENDL;
std::cout << "Current log size: " << rsp.current_log_size << ENDL;
if (start_offset >= rsp.current_log_size)
{
std::cout << "ERROR: invalid start offset: " << start_offset << ", log size: " << rsp.current_log_size << ENDL;
return false;
}
std::cout << "Downloading..." << ENDL;
std::string local_filename = tools::get_default_data_dir() + "/log_" + epee::string_tools::num_to_string_fast(peer_id) + ".log";
std::ofstream log{ local_filename, std::ifstream::binary };
if (!log)
{
std::cout << "Couldn't open " << local_filename << " for writing." << ENDL;
return false;
}
const uint64_t chunk_size = 1024 * 1024 * 5;
uint64_t end_offset = start_offset;
uint64_t bytes = 0;
while (true)
{
req.log_chunk_offset = end_offset;
req.log_chunk_size = std::min(chunk_size, rsp.current_log_size - req.log_chunk_offset);
if (req.log_chunk_size == 0)
break;
std::this_thread::sleep_for(std::chrono::seconds(1));
if (!invoke_debug_command<COMMAND_REQUEST_LOG>(vm, sk, transport, peer_id, req, rsp) || !rsp.error.empty())
{
std::cout << "ERROR: invoking COMMAND_REQUEST_LOG failed: " << rsp.error << ENDL;
return false;
}
if (!epee::zlib_helper::unpack(rsp.log_chunk))
{
std::cout << "ERROR: zip unpack failed" << ENDL;
return false;
}
if (rsp.log_chunk.size() != req.log_chunk_size)
{
std::cout << "ERROR: unpacked size: " << rsp.log_chunk.size() << ", requested: " << req.log_chunk_size << ENDL;
return false;
}
log.write(rsp.log_chunk.c_str(), rsp.log_chunk.size());
end_offset += req.log_chunk_size;
std::cout << end_offset - start_offset << " bytes downloaded" << ENDL;
}
std::cout << "Remote log from offset " << start_offset << " to offset " << end_offset << " (" << end_offset - start_offset << " bytes) " <<
"was successfully downloaded to " << local_filename;
return true;
}
//---------------------------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
@ -874,7 +1035,9 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_genesis_split_amount);
command_line::add_arg(desc_params, arg_get_info_flags);
command_line::add_arg(desc_params, arg_log_journal_len);
command_line::add_arg(desc_params, arg_set_peer_log_level);
command_line::add_arg(desc_params, arg_download_peer_log);
po::options_description desc_all;
@ -931,6 +1094,14 @@ int main(int argc, char* argv[])
{
return generate_genesis(command_line::get_arg(vm, arg_generate_genesis), 10000000000000000) ? 0 : 1;
}
else if (command_line::has_arg(vm, arg_set_peer_log_level))
{
return handle_set_peer_log_level(vm) ? 0 : 1;
}
else if (command_line::has_arg(vm, arg_download_peer_log))
{
return handle_download_peer_log(vm) ? 0 : 1;
}
else
{
std::cerr << "Not enough arguments." << ENDL;

View file

@ -77,27 +77,16 @@ namespace crypto {
memcpy(&res, tmp, 32);
}
void crypto_ops::keys_from_short(unsigned char* a_part, public_key &pub, secret_key &sec)
void crypto_ops::keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec, size_t brain_wallet_seed_size)
{
unsigned char tmp[64] = { 0 };
static_assert(sizeof tmp >= BRAINWALLET_SHORT_SEED_SIZE, "size mismatch");
memcpy(tmp, a_part, BRAINWALLET_SHORT_SEED_SIZE);
cn_fast_hash(tmp, 16, (char*)&tmp[16]);
cn_fast_hash(tmp, 32, (char*)&tmp[32]);
if (!(sizeof(tmp) >= brain_wallet_seed_size))
{
throw std::runtime_error("size mismatch");
}
sc_reduce(tmp);
memcpy(&sec, tmp, 32);
ge_p3 point;
ge_scalarmult_base(&point, &sec);
ge_p3_tobytes(&pub, &point);
}
void crypto_ops::keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec)
{
unsigned char tmp[64] = { 0 };
static_assert(sizeof tmp >= BRAINWALLET_DEFAULT_SEED_SIZE, "size mismatch");
memcpy(tmp, a_part, BRAINWALLET_DEFAULT_SEED_SIZE);
memcpy(tmp, a_part, brain_wallet_seed_size);
cn_fast_hash(tmp, 32, (char*)&tmp[32]);
@ -108,12 +97,14 @@ namespace crypto {
ge_p3_tobytes(&pub, &point);
}
void crypto_ops::generate_brain_keys(public_key &pub, secret_key &sec, std::string& seed)
void crypto_ops::generate_brain_keys(public_key &pub, secret_key &sec, std::string& seed, size_t brain_wallet_seed_size)
{
unsigned char tmp[BRAINWALLET_DEFAULT_SEED_SIZE];
generate_random_bytes(BRAINWALLET_DEFAULT_SEED_SIZE, tmp);
seed.assign((const char*)tmp, BRAINWALLET_DEFAULT_SEED_SIZE);
keys_from_default(tmp, pub, sec);
std::vector<unsigned char> tmp_vector;
tmp_vector.resize(brain_wallet_seed_size, 0);
unsigned char *tmp = &tmp_vector[0];
generate_random_bytes(brain_wallet_seed_size, tmp);
seed.assign((const char*)tmp, brain_wallet_seed_size);
keys_from_default(tmp, pub, sec, brain_wallet_seed_size);
}
static inline void hash_to_scalar(const void *data, size_t length, ec_scalar &res)

View file

@ -20,8 +20,6 @@
PUSH_WARNINGS
DISABLE_CLANG_WARNING(unused-private-field)
#define BRAINWALLET_DEFAULT_SEED_SIZE 32
#define BRAINWALLET_SHORT_SEED_SIZE 16
namespace crypto {
@ -75,12 +73,10 @@ namespace crypto {
static void generate_keys(public_key &, secret_key &);
friend void generate_keys(public_key &, secret_key &);
static void generate_brain_keys(public_key &, secret_key &, std::string& seed);
friend void generate_brain_keys(public_key &, secret_key &, std::string& seed);
static void keys_from_short(unsigned char* a_part, public_key &pub, secret_key &sec);
friend void keys_from_short(unsigned char* a_part, public_key &pub, secret_key &sec);
static void keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec);
friend void keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec);
static void generate_brain_keys(public_key &, secret_key &, std::string& seed, size_t brain_wallet_seed_size);
friend void generate_brain_keys(public_key &, secret_key &, std::string& seed, size_t brain_wallet_seed_size);
static void keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec, size_t brain_wallet_seed_size);
friend void keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec, size_t brain_wallet_seed_size);
static void dependent_key(const secret_key& first, secret_key& second);
friend void dependent_key(const secret_key& first, secret_key& second);
static bool check_key(const public_key &);
@ -139,19 +135,14 @@ namespace crypto {
crypto_ops::generate_keys(pub, sec);
}
inline void generate_brain_keys(public_key &pub, secret_key &sec, std::string& seed) {
crypto_ops::generate_brain_keys(pub, sec, seed);
}
inline void keys_from_short(unsigned char* a_part, public_key &pub, secret_key &sec)
{
crypto_ops::keys_from_short(a_part, pub, sec);
inline void generate_brain_keys(public_key &pub, secret_key &sec, std::string& seed, size_t brain_wallet_seed_size) {
crypto_ops::generate_brain_keys(pub, sec, seed, brain_wallet_seed_size);
}
inline void keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec)
inline void keys_from_default(unsigned char* a_part, public_key &pub, secret_key &sec, size_t brain_wallet_seed_size)
{
crypto_ops::keys_from_default(a_part, pub, sec);
crypto_ops::keys_from_default(a_part, pub, sec, brain_wallet_seed_size);
}
inline void dependent_key(const secret_key& first, secret_key& second){

View file

@ -41,9 +41,8 @@ namespace currency
}
//-----------------------------------------------------------------
void account_base::generate()
{
//generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key);
generate_brain_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, m_seed);
{
generate_brain_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, m_seed, BRAINWALLET_DEFAULT_SEED_SIZE);
dependent_key(m_keys.m_spend_secret_key, m_keys.m_view_secret_key);
if (!crypto::secret_key_to_public_key(m_keys.m_view_secret_key, m_keys.m_account_address.m_view_public_key))
throw std::runtime_error("Failed to create public view key");
@ -62,12 +61,16 @@ namespace currency
return m_seed;
}
//-----------------------------------------------------------------
std::string account_base::get_restore_braindata() const
{
std::string restore_buff = get_restore_data();
std::vector<unsigned char> v;
v.assign((unsigned char*)restore_buff.data(), (unsigned char*)restore_buff.data() + restore_buff.size());
return tools::mnemonic_encoding::binary2text(v);
std::string seed_brain_data = tools::mnemonic_encoding::binary2text(v);
std::string timestamp_word = currency::get_word_from_timstamp(m_creation_timestamp);
seed_brain_data = seed_brain_data + timestamp_word;
return seed_brain_data;
}
//-----------------------------------------------------------------
bool account_base::restore_keys(const std::string& restore_data)
@ -75,11 +78,7 @@ namespace currency
//CHECK_AND_ASSERT_MES(restore_data.size() == ACCOUNT_RESTORE_DATA_SIZE, false, "wrong restore data size");
if (restore_data.size() == BRAINWALLET_DEFAULT_SEED_SIZE)
{
crypto::keys_from_default((unsigned char*)restore_data.data(), m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key);
}
else if(restore_data.size() == BRAINWALLET_SHORT_SEED_SIZE)
{
crypto::keys_from_short((unsigned char*)restore_data.data(), m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key);
crypto::keys_from_default((unsigned char*)restore_data.data(), m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, BRAINWALLET_DEFAULT_SEED_SIZE);
}
else
{
@ -94,15 +93,27 @@ namespace currency
return true;
}
//-----------------------------------------------------------------
bool account_base::restore_keys_from_braindata(const std::string& restore_data)
bool account_base::restore_keys_from_braindata(const std::string& restore_data_)
{
//cut the last timestamp word from restore_dats
std::list<std::string> words;
boost::split(words, restore_data_, boost::is_space());
CHECK_AND_ASSERT_THROW_MES(words.size() == BRAINWALLET_DEFAULT_WORDS_COUNT, "Words count missmatch: " << words.size());
std::string timestamp_word = words.back();
words.erase(--words.end());
std::string restore_data_local = boost::algorithm::join(words, " ");
std::vector<unsigned char> bin = tools::mnemonic_encoding::text2binary(restore_data);
std::vector<unsigned char> bin = tools::mnemonic_encoding::text2binary(restore_data_local);
if (!bin.size())
return false;
std::string restore_buff((const char*)&bin[0], bin.size());
return restore_keys(restore_buff);
bool r = restore_keys(restore_buff);
CHECK_AND_ASSERT_MES(r, false, "restore_keys failed");
m_creation_timestamp = get_timstamp_from_word(timestamp_word);
return true;
}
//-----------------------------------------------------------------
std::string account_base::get_public_address_str()

View file

@ -10,9 +10,9 @@
#include "crypto/crypto.h"
#include "serialization/keyvalue_serialization.h"
#define BRAINWALLET_DEFAULT_SEED_SIZE 32
#define ACCOUNT_RESTORE_DATA_SIZE BRAINWALLET_DEFAULT_SEED_SIZE
#define BRAINWALLET_DEFAULT_WORDS_COUNT 25

View file

@ -4254,7 +4254,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
return false;
}
uint64_t h = get_block_height(bl);
get_block_height(bl);
if(!check_block_timestamp_main(bl))
{

View file

@ -155,6 +155,10 @@
#define WALLET_FILE_SIGNATURE 0x1111012101101011LL //Bender's nightmare
#define WALLET_FILE_MAX_BODY_SIZE 0x88888888L //2GB
#define WALLET_FILE_MAX_KEYS_SIZE 10000 //
#define WALLET_BRAIN_DATE_OFFSET 1543622400
#define WALLET_BRAIN_DATE_QUANTUM 604800 //by last word we encode a number of week since launch of the project,
//which let us to address tools::mnemonic_encoding::NUMWORDS weeks after project launch
//which is about 30 years
#define OFFER_MAXIMUM_LIFE_TIME (60*60*24*30) // 30 days

View file

@ -26,54 +26,18 @@ using namespace epee;
#include "bc_attachments_helpers.h"
#include "genesis.h"
#include "genesis_acc.h"
#include "common/mnemonic-encoding.h"
namespace currency
{
//---------------------------------------------------------------
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h)
{
std::ostringstream s;
binary_archive<true> a(s);
::serialization::serialize(a, const_cast<transaction_prefix&>(tx));
std::string data = s.str();
crypto::cn_fast_hash(data.data(), data.size(), h);
}
//---------------------------------------------------------------
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx)
{
crypto::hash h = null_hash;
get_transaction_prefix_hash(tx, h);
return h;
}
//---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx)
{
std::stringstream ss;
ss << tx_blob;
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
return true;
}
//---------------------------------------------------------------
bool add_tx_extra_alias(transaction& tx, const extra_alias_entry& alinfo)
{
tx.extra.push_back(alinfo);
return true;
}
//---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash)
{
std::stringstream ss;
ss << tx_blob;
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
//TODO: validate tx
//crypto::cn_fast_hash(tx_blob.data(), tx_blob.size(), tx_hash);
get_transaction_prefix_hash(tx, tx_hash);
return true;
}
//---------------------------------------------------------------
/*
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins,
@ -1246,6 +1210,24 @@ namespace currency
return reward;
}
//---------------------------------------------------------------
std::string get_word_from_timstamp(uint64_t timestamp)
{
uint64_t date_offset = timestamp ? timestamp - WALLET_BRAIN_DATE_OFFSET : 0;
uint64_t weeks_count = date_offset / WALLET_BRAIN_DATE_QUANTUM;
CHECK_AND_ASSERT_THROW_MES(weeks_count < std::numeric_limits<uint32_t>::max(), "internal error: unable to converto to uint32, val = " << weeks_count);
uint32_t weeks_count_32 = static_cast<uint32_t>(weeks_count);
return tools::mnemonic_encoding::word_by_num(weeks_count_32);
}
//---------------------------------------------------------------
uint64_t get_timstamp_from_word(std::string word)
{
uint64_t count_of_weeks = tools::mnemonic_encoding::num_by_word(word);
uint64_t timestamp = count_of_weeks * WALLET_BRAIN_DATE_QUANTUM + WALLET_BRAIN_DATE_OFFSET;
return timestamp;
}
//---------------------------------------------------------------
bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed /* = nullptr */)
{
#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, msg << ", ms input index: " << ms_input_index << ", tx: " << get_transaction_hash(tx) << ", source tx: " << get_transaction_hash(source_tx))
@ -1620,11 +1602,7 @@ namespace currency
att.push_back(tsa);
return true;
}
//---------------------------------------------------------------
void get_blob_hash(const blobdata& blob, crypto::hash& res)
{
cn_fast_hash(blob.data(), blob.size(), res);
}
std::string print_fixed_decimal_point(uint64_t amount, size_t decimal_point)
{
@ -1648,32 +1626,6 @@ namespace currency
return std::to_string(amount) + '.' + r.substr(0, r.find_last_not_of('0') + 1);
}
//---------------------------------------------------------------
crypto::hash get_blob_hash(const blobdata& blob)
{
crypto::hash h = null_hash;
get_blob_hash(blob, h);
return h;
}
//---------------------------------------------------------------
crypto::hash get_transaction_hash(const transaction& t)
{
return get_transaction_prefix_hash(t);
}
//---------------------------------------------------------------
bool get_transaction_hash(const transaction& t, crypto::hash& res)
{
uint64_t blob_size = 0;
return get_object_hash(static_cast<const transaction_prefix&>(t), res, blob_size);
}
//---------------------------------------------------------------
bool get_transaction_hash(const transaction& t, crypto::hash& res, uint64_t& blob_size)
{
blob_size = 0;
bool r = get_object_hash(static_cast<const transaction_prefix&>(t), res, blob_size);
blob_size = get_object_blobsize(t, blob_size);
return r;
}
//---------------------------------------------------------------
/*bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
{
@ -1926,27 +1878,6 @@ namespace currency
return ss.str();
}
//---------------------------------------------------------------
blobdata get_block_hashing_blob(const block& b)
{
blobdata blob = t_serializable_object_to_blob(static_cast<block_header>(b));
crypto::hash tree_root_hash = get_tx_tree_hash(b);
blob.append((const char*)&tree_root_hash, sizeof(tree_root_hash));
blob.append(tools::get_varint_data(b.tx_hashes.size() + 1));
return blob;
}
//---------------------------------------------------------------
bool get_block_hash(const block& b, crypto::hash& res)
{
return get_object_hash(get_block_hashing_blob(b), res);
}
//---------------------------------------------------------------
crypto::hash get_block_hash(const block& b)
{
crypto::hash p = null_hash;
get_block_hash(b, p);
return p;
}
//---------------------------------------------------------------
bool generate_genesis_block(block& bl)
{
//genesis block
@ -2052,101 +1983,9 @@ namespace currency
//---------------------------------------------------------------
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b)
{
return t_unserializable_object_from_blob(b, b_blob);
return parse_and_validate_object_from_blob(b_blob, b);
}
//---------------------------------------------------------------
size_t get_object_blobsize(const transaction& t)
{
size_t tx_blob_size = get_object_blobsize(static_cast<const transaction_prefix&>(t));
return get_object_blobsize(t, tx_blob_size);
}
//---------------------------------------------------------------
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size)
{
size_t tx_blob_size = prefix_blob_size;
if (is_coinbase(t))
return tx_blob_size;
// for purged tx, with empty signatures and attachments, this function should return the blob size
// which the tx would have if the signatures and attachments were correctly filled with actual data
// 1. signatures
bool separately_signed_tx = get_tx_flags(t) & TX_FLAG_SIGNATURE_MODE_SEPARATE;
tx_blob_size += tools::get_varint_packed_size(t.vin.size()); // size of transaction::signatures (equals to total inputs count)
for (size_t i = 0; i != t.vin.size(); i++)
{
size_t sig_count = get_input_expected_signatures_count(t.vin[i]);
if (separately_signed_tx && i == t.vin.size() - 1)
++sig_count; // count in one more signature for the last input in a complete separately signed tx
tx_blob_size += tools::get_varint_packed_size(sig_count); // size of transaction::signatures[i]
tx_blob_size += sizeof(crypto::signature) * sig_count; // size of signatures' data itself
}
// 2. attachments (try to find extra_attachment_info in tx prefix and count it in if succeed)
extra_attachment_info eai = AUTO_VAL_INIT(eai);
bool got_eai = false;
if (separately_signed_tx)
{
// for separately-signed tx, try to obtain extra_attachment_info from the last input's etc_details
const std::vector<txin_etc_details_v>* p_etc_details = get_input_etc_details(t.vin.back());
got_eai = p_etc_details != nullptr && get_type_in_variant_container(*p_etc_details, eai);
}
if (!got_eai)
got_eai = get_type_in_variant_container(t.extra, eai); // then from the extra
if (got_eai)
tx_blob_size += eai.sz; // sz is a size of whole serialized attachment blob, including attachments vector size
else
tx_blob_size += tools::get_varint_packed_size(static_cast<size_t>(0)); // no extra_attachment_info found - just add zero vector's size, 'cause it's serialized anyway
return tx_blob_size;
}
//---------------------------------------------------------------
blobdata block_to_blob(const block& b)
{
return t_serializable_object_to_blob(b);
}
//---------------------------------------------------------------
bool block_to_blob(const block& b, blobdata& b_blob)
{
return t_serializable_object_to_blob(b, b_blob);
}
//---------------------------------------------------------------
blobdata tx_to_blob(const transaction& tx)
{
return t_serializable_object_to_blob(tx);
}
//---------------------------------------------------------------
bool tx_to_blob(const transaction& tx, blobdata& b_blob)
{
return t_serializable_object_to_blob(tx, b_blob);
}
//---------------------------------------------------------------
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h)
{
tree_hash(tx_hashes.data(), tx_hashes.size(), h);
}
//---------------------------------------------------------------
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes)
{
crypto::hash h = null_hash;
get_tx_tree_hash(tx_hashes, h);
return h;
}
//---------------------------------------------------------------
crypto::hash get_tx_tree_hash(const block& b)
{
std::vector<crypto::hash> txs_ids;
crypto::hash h = null_hash;
get_transaction_hash(b.miner_tx, h);
txs_ids.push_back(h);
BOOST_FOREACH(auto& th, b.tx_hashes)
txs_ids.push_back(th);
return get_tx_tree_hash(txs_ids);
}
//---------------------------------------------------------------
bool is_service_tx(const transaction& tx)
{

View file

@ -11,10 +11,12 @@
#include <unordered_set>
#include <unordered_map>
#include "currency_protocol/currency_protocol_defs.h"
#include "account.h"
#include "include_base_utils.h"
#include "currency_format_utils_abstract.h"
#include "common/crypto_stream_operators.h"
#include "currency_protocol/currency_protocol_defs.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "difficulty.h"
@ -23,6 +25,8 @@
#include "bc_payments_id_service.h"
#include "bc_attachments_helpers_basic.h"
#include "blockchain_storage_basic.h"
#include "currency_format_utils_blocks.h"
#include "currency_format_utils_transactions.h"
// ------ get_tx_type_definition -------------
#define GUI_TX_TYPE_NORMAL 0
@ -42,31 +46,8 @@
//------
bool parse_hash256(const std::string str_hash, crypto::hash& hash);
template <class T>
std::ostream &print256(std::ostream &o, const T &v) {
return o << "<" << epee::string_tools::pod_to_hex(v) << ">";
}
template <class T>
std::ostream &print16(std::ostream &o, const T &v) {
return o << "<" << epee::string_tools::pod_to_hex(v).substr(0, 5) << "..>";
}
template <class T>
std::string print16(const T &v) {
return std::string("<") + epee::string_tools::pod_to_hex(v).substr(0, 5) + "..>";
}
namespace crypto {
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); }
}
namespace currency
{
@ -182,10 +163,6 @@ namespace currency
//---------------------------------------------------------------
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h);
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins,
size_t current_block_size,
uint64_t fee,
@ -234,14 +211,6 @@ namespace currency
bool is_tx_expired(const transaction& tx, uint64_t expiration_ts_median);
template<class t_type>
std::string print_t_array(const std::vector<t_type>& vec)
{
std::stringstream ss;
for (auto& v : vec)
ss << v << " ";
return ss.str();
}
uint64_t get_string_uint64_hash(const std::string& str);
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
@ -302,8 +271,6 @@ namespace currency
bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki);
bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation);
bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key);
void get_blob_hash(const blobdata& blob, crypto::hash& res);
crypto::hash get_blob_hash(const blobdata& blob);
std::string short_hash_str(const crypto::hash& h);
bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_attr_count);
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time);
@ -316,13 +283,7 @@ namespace currency
uint64_t get_reward_from_miner_tx(const transaction& tx);
crypto::hash get_transaction_hash(const transaction& t);
bool get_transaction_hash(const transaction& t, crypto::hash& res);
bool get_transaction_hash(const transaction& t, crypto::hash& res, uint64_t& blob_size);
//bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
blobdata get_block_hashing_blob(const block& b);
bool get_block_hash(const block& b, crypto::hash& res);
crypto::hash get_block_hash(const block& b);
bool generate_genesis_block(block& bl);
const crypto::hash& get_genesis_hash(bool need_to_set = false, const crypto::hash& h = null_hash);
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
@ -389,18 +350,8 @@ namespace currency
bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false);
bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h);
void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map<uint64_t, uint32_t>& gindices);
/************************************************************************/
/* */
/************************************************************************/
template<class t_array>
struct array_hasher : std::unary_function<t_array&, std::size_t>
{
std::size_t operator()(const t_array& val) const
{
return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]);
}
};
std::string get_word_from_timstamp(uint64_t timestamp);
uint64_t get_timstamp_from_word(std::string word);
template<class t_txin_v>
typename std::conditional<std::is_const<t_txin_v>::value, const std::vector<txin_etc_details_v>, std::vector<txin_etc_details_v> >::type& get_txin_etc_options(t_txin_v& in)
@ -450,17 +401,6 @@ namespace currency
bool have_attachment_service_in_container(const std::vector<attachment_v>& av, const std::string& service_id, const std::string& instruction);
crypto::hash prepare_prefix_hash_for_sign(const transaction& tx, uint64_t in_index, const crypto::hash& tx_id);
//------------------------------------------------------------------------------------
template<class t_pod_type, class result_type>
result_type get_pod_checksum(const t_pod_type& bl)
{
const unsigned char* pbuf = reinterpret_cast<const unsigned char*>(&bl);
result_type summ = 0;
for (size_t i = 0; i != sizeof(t_pod_type)-1; i++)
summ += pbuf[i];
return summ;
}
//---------------------------------------------------------------
template<class tx_out_t>
bool is_out_to_acc(const account_keys& acc, const tx_out_t& out_key, const crypto::public_key& tx_pub_key, size_t output_index)
@ -469,83 +409,6 @@ namespace currency
generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
return is_out_to_acc(acc, out_key, derivation, output_index);
}
//---------------------------------------------------------------
template<typename specic_type_t, typename variant_t_container>
bool have_type_in_variant_container(const variant_t_container& av)
{
for (auto& ai : av)
{
if (ai.type() == typeid(specic_type_t))
{
return true;
}
}
return false;
}
//---------------------------------------------------------------
template<typename specic_type_t, typename variant_t_container>
size_t count_type_in_variant_container(const variant_t_container& av)
{
size_t result = 0;
for (auto& ai : av)
{
if (ai.type() == typeid(specic_type_t))
++result;
}
return result;
}
//---------------------------------------------------------------
template<typename specic_type_t, typename variant_t_container>
bool get_type_in_variant_container(const variant_t_container& av, specic_type_t& a)
{
for (auto& ai : av)
{
if (ai.type() == typeid(specic_type_t))
{
a = boost::get<specic_type_t>(ai);
return true;
}
}
return false;
}
//---------------------------------------------------------------
template<typename variant_container_t>
bool check_allowed_types_in_variant_container(const variant_container_t& container, const std::unordered_set<std::type_index>& allowed_types, bool elements_must_be_unique = true)
{
for (auto it = container.begin(); it != container.end(); ++it)
{
if (allowed_types.count(std::type_index(it->type())) == 0)
return false;
if (elements_must_be_unique)
{
for (auto jt = it + 1; jt != container.end(); ++jt)
if (it->type().hash_code() == jt->type().hash_code())
return false;
}
}
return true;
}
//---------------------------------------------------------------
template<typename variant_container_t>
bool check_allowed_types_in_variant_container(const variant_container_t& container, const variant_container_t& allowed_types_examples, bool elements_must_be_unique = true)
{
std::unordered_set<std::type_index> allowed_types;
for (auto& el : allowed_types_examples)
if (!allowed_types.insert(std::type_index(el.type())).second)
return false; // invalid allowed_types_examples container
return check_allowed_types_in_variant_container(container, allowed_types, elements_must_be_unique);
}
//---------------------------------------------------------------
template<typename variant_container_t>
std::string stringize_types_in_variant_container(const variant_container_t& container)
{
std::string result;
for (auto it = container.begin(); it != container.end(); ++it)
result = (result + it->type().name()) + (it + 1 != container.end() ? ", " : "");
return result;
}
//----------------------------------------------------------------------------------------------------
template<class t_container>
bool validate_attachment_info(const t_container& container, const std::vector<attachment_v>& attachments, bool allow_no_info_for_non_empty_attachments_container)
@ -692,51 +555,7 @@ namespace currency
return true;
}
//---------------------------------------------------------------
template<class t_object>
bool get_object_hash(const t_object& o, crypto::hash& res)
{
get_blob_hash(t_serializable_object_to_blob(o), res);
return true;
}
//---------------------------------------------------------------
template<class t_object>
crypto::hash get_object_hash(const t_object& o)
{
crypto::hash h;
get_object_hash(o, h);
return h;
}
//---------------------------------------------------------------
template<class t_object>
size_t get_object_blobsize(const t_object& o)
{
blobdata b = t_serializable_object_to_blob(o);
return b.size();
}
//---------------------------------------------------------------
size_t get_object_blobsize(const transaction& t);
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
//---------------------------------------------------------------
template<class t_object>
bool get_object_hash(const t_object& o, crypto::hash& res, uint64_t& blob_size)
{
blobdata bl = t_serializable_object_to_blob(o);
blob_size = bl.size();
get_blob_hash(bl, res);
return true;
}
//---------------------------------------------------------------
template <typename T>
std::string obj_to_json_str(const T& obj)
{
std::stringstream ss;
json_archive<true> ar(ss, true);
bool r = ::serialization::serialize(ar, const_cast<T&>(obj));
CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false");
return ss.str();
}
//---------------------------------------------------------------
// 62387455827 -> 455827 + 7000000 + 80000000 + 300000000 + 2000000000 + 60000000000, where 455827 <= dust_threshold
template<typename chunk_handler_t, typename dust_handler_t>
@ -843,18 +662,6 @@ namespace currency
}
//---------------------------------------------------------------
blobdata block_to_blob(const block& b);
bool block_to_blob(const block& b, blobdata& b_blob);
blobdata tx_to_blob(const transaction& b);
bool tx_to_blob(const transaction& b, blobdata& b_blob);
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h);
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
crypto::hash get_tx_tree_hash(const block& b);
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
specific_type& variable_name = boost::get<specific_type>(variant_var);
struct input_amount_getter : public boost::static_visitor<uint64_t>
{
template<class t_input>
@ -866,7 +673,6 @@ namespace currency
{
return boost::apply_visitor(input_amount_getter(), v);
}
//---------------------------------------------------------------
std::ostream& operator <<(std::ostream& o, const ref_by_id& r);
//---------------------------------------------------------------

View file

@ -0,0 +1,218 @@
// Copyright (c) 2018-2019 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <typeindex>
#include <unordered_set>
#include <unordered_map>
#include <list>
#include <memory>
#include "include_base_utils.h"
#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage_template_helper.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "currency_core/currency_basic.h"
#include "currency_protocol/blobdatatype.h"
#include "common/crypto_stream_operators.h"
namespace currency
{
template<typename type_t>
std::string print_kv_structure(const type_t& v)
{
return epee::serialization::store_t_to_json(v);
}
template<class t_type>
std::string print_t_array(const std::vector<t_type>& vec)
{
std::stringstream ss;
for (auto& v : vec)
ss << v << " ";
return ss.str();
}
/************************************************************************/
/* */
/************************************************************************/
template<class t_array>
struct array_hasher : std::unary_function<t_array&, std::size_t>
{
std::size_t operator()(const t_array& val) const
{
return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]);
}
};
//------------------------------------------------------------------------------------
template<class t_pod_type, class result_type>
result_type get_pod_checksum(const t_pod_type& bl)
{
const unsigned char* pbuf = reinterpret_cast<const unsigned char*>(&bl);
result_type summ = 0;
for (size_t i = 0; i != sizeof(t_pod_type)-1; i++)
summ += pbuf[i];
return summ;
}
template<typename object_t>
bool parse_and_validate_object_from_blob(const blobdata& b_blob, object_t& b)
{
return t_unserializable_object_from_blob(b, b_blob);
}
//---------------------------------------------------------------
template<typename specic_type_t, typename variant_t_container>
bool have_type_in_variant_container(const variant_t_container& av)
{
for (auto& ai : av)
{
if (ai.type() == typeid(specic_type_t))
{
return true;
}
}
return false;
}
//---------------------------------------------------------------
template<typename specic_type_t, typename variant_t_container>
size_t count_type_in_variant_container(const variant_t_container& av)
{
size_t result = 0;
for (auto& ai : av)
{
if (ai.type() == typeid(specic_type_t))
++result;
}
return result;
}
//---------------------------------------------------------------
template<typename specic_type_t, typename variant_t_container>
bool get_type_in_variant_container(const variant_t_container& av, specic_type_t& a)
{
for (auto& ai : av)
{
if (ai.type() == typeid(specic_type_t))
{
a = boost::get<specic_type_t>(ai);
return true;
}
}
return false;
}
//---------------------------------------------------------------
template<typename variant_container_t>
bool check_allowed_types_in_variant_container(const variant_container_t& container, const std::unordered_set<std::type_index>& allowed_types, bool elements_must_be_unique = true)
{
for (auto it = container.begin(); it != container.end(); ++it)
{
if (allowed_types.count(std::type_index(it->type())) == 0)
return false;
if (elements_must_be_unique)
{
for (auto jt = it + 1; jt != container.end(); ++jt)
if (it->type().hash_code() == jt->type().hash_code())
return false;
}
}
return true;
}
//---------------------------------------------------------------
template<typename variant_container_t>
bool check_allowed_types_in_variant_container(const variant_container_t& container, const variant_container_t& allowed_types_examples, bool elements_must_be_unique = true)
{
std::unordered_set<std::type_index> allowed_types;
for (auto& el : allowed_types_examples)
if (!allowed_types.insert(std::type_index(el.type())).second)
return false; // invalid allowed_types_examples container
return check_allowed_types_in_variant_container(container, allowed_types, elements_must_be_unique);
}
//---------------------------------------------------------------
template<typename variant_container_t>
std::string stringize_types_in_variant_container(const variant_container_t& container)
{
std::string result;
for (auto it = container.begin(); it != container.end(); ++it)
result = (result + it->type().name()) + (it + 1 != container.end() ? ", " : "");
return result;
}
//---------------------------------------------------------------
inline
void get_blob_hash(const blobdata& blob, crypto::hash& res)
{
cn_fast_hash(blob.data(), blob.size(), res);
}
//---------------------------------------------------------------
inline
crypto::hash get_blob_hash(const blobdata& blob)
{
crypto::hash h = null_hash;
get_blob_hash(blob, h);
return h;
}
template<class t_object>
bool get_object_hash(const t_object& o, crypto::hash& res)
{
get_blob_hash(t_serializable_object_to_blob(o), res);
return true;
}
//---------------------------------------------------------------
template<class t_object>
crypto::hash get_object_hash(const t_object& o)
{
crypto::hash h;
get_object_hash(o, h);
return h;
}
//---------------------------------------------------------------
template<class t_object>
size_t get_object_blobsize(const t_object& o)
{
blobdata b = t_serializable_object_to_blob(o);
return b.size();
}
//---------------------------------------------------------------
template<class t_object>
bool get_object_hash(const t_object& o, crypto::hash& res, uint64_t& blob_size)
{
blobdata bl = t_serializable_object_to_blob(o);
blob_size = bl.size();
get_blob_hash(bl, res);
return true;
}
//---------------------------------------------------------------
template <typename T>
std::string obj_to_json_str(const T& obj)
{
std::stringstream ss;
json_archive<true> ar(ss, true);
bool r = ::serialization::serialize(ar, const_cast<T&>(obj));
CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false");
return ss.str();
}
//---------------------------------------------------------------
//---------------------------------------------------------------
size_t get_object_blobsize(const transaction& t);
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
specific_type& variable_name = boost::get<specific_type>(variant_var);
} // namespace currency

View file

@ -0,0 +1,67 @@
// Copyright (c) 2018-2019 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "currency_format_utils_blocks.h"
#include "serialization/serialization.h"
#include "currency_format_utils_abstract.h"
#include "currency_format_utils_transactions.h"
namespace currency
{
//---------------------------------------------------------------
blobdata get_block_hashing_blob(const block& b)
{
blobdata blob = t_serializable_object_to_blob(static_cast<block_header>(b));
crypto::hash tree_root_hash = get_tx_tree_hash(b);
blob.append((const char*)&tree_root_hash, sizeof(tree_root_hash));
blob.append(tools::get_varint_data(b.tx_hashes.size() + 1));
return blob;
}
//---------------------------------------------------------------
bool get_block_hash(const block& b, crypto::hash& res)
{
return get_object_hash(get_block_hashing_blob(b), res);
}
//---------------------------------------------------------------
crypto::hash get_block_hash(const block& b)
{
crypto::hash p = null_hash;
get_block_hash(b, p);
return p;
}
//---------------------------------------------------------------
blobdata block_to_blob(const block& b)
{
return t_serializable_object_to_blob(b);
}
//---------------------------------------------------------------
bool block_to_blob(const block& b, blobdata& b_blob)
{
return t_serializable_object_to_blob(b, b_blob);
}
//---------------------------------------------------------------
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h)
{
tree_hash(tx_hashes.data(), tx_hashes.size(), h);
}
//---------------------------------------------------------------
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes)
{
crypto::hash h = null_hash;
get_tx_tree_hash(tx_hashes, h);
return h;
}
//---------------------------------------------------------------
crypto::hash get_tx_tree_hash(const block& b)
{
std::vector<crypto::hash> txs_ids;
crypto::hash h = null_hash;
get_transaction_hash(b.miner_tx, h);
txs_ids.push_back(h);
BOOST_FOREACH(auto& th, b.tx_hashes)
txs_ids.push_back(th);
return get_tx_tree_hash(txs_ids);
}
}

View file

@ -0,0 +1,25 @@
// Copyright (c) 2018-2019 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "include_base_utils.h"
#include "crypto/crypto.h"
#include "currency_core/currency_basic.h"
#include "currency_protocol/blobdatatype.h"
namespace currency
{
blobdata get_block_hashing_blob(const block& b);
bool get_block_hash(const block& b, crypto::hash& res);
crypto::hash get_block_hash(const block& b);
blobdata block_to_blob(const block& b);
bool block_to_blob(const block& b, blobdata& b_blob);
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h);
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
crypto::hash get_tx_tree_hash(const block& b);
}

View file

@ -0,0 +1,134 @@
// Copyright (c) 2018-2019 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "currency_format_utils_transactions.h"
#include "serialization/serialization.h"
#include "currency_format_utils_abstract.h"
#include "currency_format_utils.h"
namespace currency
{
//---------------------------------------------------------------
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h)
{
std::ostringstream s;
binary_archive<true> a(s);
::serialization::serialize(a, const_cast<transaction_prefix&>(tx));
std::string data = s.str();
crypto::cn_fast_hash(data.data(), data.size(), h);
}
//---------------------------------------------------------------
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx)
{
crypto::hash h = null_hash;
get_transaction_prefix_hash(tx, h);
return h;
}
//---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx)
{
std::stringstream ss;
ss << tx_blob;
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
return true;
}
//---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash)
{
std::stringstream ss;
ss << tx_blob;
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
//TODO: validate tx
//crypto::cn_fast_hash(tx_blob.data(), tx_blob.size(), tx_hash);
get_transaction_prefix_hash(tx, tx_hash);
return true;
}
//---------------------------------------------------------------
crypto::hash get_transaction_hash(const transaction& t)
{
return get_transaction_prefix_hash(t);
}
//---------------------------------------------------------------
bool get_transaction_hash(const transaction& t, crypto::hash& res)
{
uint64_t blob_size = 0;
return get_object_hash(static_cast<const transaction_prefix&>(t), res, blob_size);
}
//---------------------------------------------------------------
bool get_transaction_hash(const transaction& t, crypto::hash& res, uint64_t& blob_size)
{
blob_size = 0;
bool r = get_object_hash(static_cast<const transaction_prefix&>(t), res, blob_size);
blob_size = get_object_blobsize(t, blob_size);
return r;
}
//---------------------------------------------------------------
size_t get_object_blobsize(const transaction& t)
{
size_t tx_blob_size = get_object_blobsize(static_cast<const transaction_prefix&>(t));
return get_object_blobsize(t, tx_blob_size);
}
//---------------------------------------------------------------
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size)
{
size_t tx_blob_size = prefix_blob_size;
if (is_coinbase(t))
return tx_blob_size;
// for purged tx, with empty signatures and attachments, this function should return the blob size
// which the tx would have if the signatures and attachments were correctly filled with actual data
// 1. signatures
bool separately_signed_tx = get_tx_flags(t) & TX_FLAG_SIGNATURE_MODE_SEPARATE;
tx_blob_size += tools::get_varint_packed_size(t.vin.size()); // size of transaction::signatures (equals to total inputs count)
for (size_t i = 0; i != t.vin.size(); i++)
{
size_t sig_count = get_input_expected_signatures_count(t.vin[i]);
if (separately_signed_tx && i == t.vin.size() - 1)
++sig_count; // count in one more signature for the last input in a complete separately signed tx
tx_blob_size += tools::get_varint_packed_size(sig_count); // size of transaction::signatures[i]
tx_blob_size += sizeof(crypto::signature) * sig_count; // size of signatures' data itself
}
// 2. attachments (try to find extra_attachment_info in tx prefix and count it in if succeed)
extra_attachment_info eai = AUTO_VAL_INIT(eai);
bool got_eai = false;
if (separately_signed_tx)
{
// for separately-signed tx, try to obtain extra_attachment_info from the last input's etc_details
const std::vector<txin_etc_details_v>* p_etc_details = get_input_etc_details(t.vin.back());
got_eai = p_etc_details != nullptr && get_type_in_variant_container(*p_etc_details, eai);
}
if (!got_eai)
got_eai = get_type_in_variant_container(t.extra, eai); // then from the extra
if (got_eai)
tx_blob_size += eai.sz; // sz is a size of whole serialized attachment blob, including attachments vector size
else
tx_blob_size += tools::get_varint_packed_size(static_cast<size_t>(0)); // no extra_attachment_info found - just add zero vector's size, 'cause it's serialized anyway
return tx_blob_size;
}
//---------------------------------------------------------------
blobdata tx_to_blob(const transaction& tx)
{
return t_serializable_object_to_blob(tx);
}
//---------------------------------------------------------------
bool tx_to_blob(const transaction& tx, blobdata& b_blob)
{
return t_serializable_object_to_blob(tx, b_blob);
}
}

View file

@ -0,0 +1,27 @@
// Copyright (c) 2018-2019 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "include_base_utils.h"
#include "crypto/crypto.h"
#include "currency_core/currency_basic.h"
#include "currency_protocol/blobdatatype.h"
namespace currency
{
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h);
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
crypto::hash get_transaction_hash(const transaction& t);
bool get_transaction_hash(const transaction& t, crypto::hash& res);
bool get_transaction_hash(const transaction& t, crypto::hash& res, uint64_t& blob_size);
size_t get_object_blobsize(const transaction& t);
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
blobdata tx_to_blob(const transaction& b);
bool tx_to_blob(const transaction& b, blobdata& b_blob);
}

View file

@ -104,7 +104,7 @@ namespace currency
{
std::list<blobdata> txs;
std::list<block_complete_entry> blocks;
std::list<crypto::hash> missed_ids;
std::list<crypto::hash> missed_ids;
uint64_t current_blockchain_height;
BEGIN_KV_SERIALIZE_MAP()
@ -168,3 +168,5 @@ namespace currency
};
}
#include "currency_protocol_defs_print.h"

View file

@ -0,0 +1,89 @@
// Copyright (c) 2014-2018 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "currency_core/currency_format_utils_abstract.h"
#include "currency_core/currency_format_utils_blocks.h"
#include "storages/portable_storage_to_json.h"
namespace currency
{
//------------------------------------------------------------------------------------------------------------------------
inline std::string print_complete_block_entry_list(const std::list<block_complete_entry>& blocks)
{
std::stringstream ss;
size_t i = 0;
for (const block_complete_entry& block_entry : blocks)
{
ss << "[" << i << "]";
block b = AUTO_VAL_INIT(b);
if (!parse_and_validate_object_from_blob(block_entry.block, b))
{
ss << "UNPARSED" << ENDL;
}
ss << get_block_hash(b) << "{....parent: " << b.prev_id << "....}" << ENDL;
i++;
}
return ss.str();
}
template<typename container_t>
std::string print_container_of_hashs(const container_t& cont, size_t indent)
{
std::stringstream ss;
std::string indent_str(indent, ' ');
for (const auto& h : cont)
{
ss << indent_str << h << ENDL;
}
return ss.str();
}
inline
std::string print_kv_structure(const NOTIFY_REQUEST_GET_OBJECTS::request& v)
{
std::stringstream ss;
ss << "blocks: {" << ENDL << print_container_of_hashs(v.blocks, 2) << ENDL << "}";
ss << "txs: {" << ENDL << print_container_of_hashs(v.txs, 2) << ENDL << "}";
return ss.str();
}
inline
std::string print_kv_structure(const NOTIFY_RESPONSE_GET_OBJECTS::request& v)
{
std::stringstream ss;
ss << "\"blocks\":{" << ENDL << print_complete_block_entry_list(v.blocks) << ENDL << "}, " << ENDL;
ss << "\"missed_ids\":" << ENDL;
::epee::serialization::dump_as_json(ss, v.missed_ids, 2);
ss << ENDL << "\"current_blockchain_height\":" << v.current_blockchain_height;
return ss.str();
}
inline
std::string print_kv_structure(const NOTIFY_REQUEST_CHAIN::request& v)
{
std::stringstream ss;
size_t i = 0;
ss << "block_ids: {" << ENDL << print_container_of_hashs(v.block_ids, 2) << ENDL << "}";
return ss.str();
}
inline
std::string print_kv_structure(const NOTIFY_RESPONSE_CHAIN_ENTRY::request& v)
{
std::stringstream ss;
ss << "start_height:" << v.start_height << ENDL;
ss << "total_height:" << v.total_height << ENDL;
ss << "block_ids: {" << ENDL;
for (const block_context_info& bei : v.m_block_ids)
{
ss << bei.h << ":" << bei.cumul_size << ENDL;
}
ss << "}";
return ss.str();
}
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
@ -70,6 +70,8 @@ namespace currency
{
NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized<NOTIFY_REQUEST_CHAIN::request>();
m_core.get_short_chain_history(r.block_ids);
LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_callback): m_block_ids.size()=" << r.block_ids.size());
LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_callback): " << ENDL << print_kv_structure(r));
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
}
@ -308,7 +310,8 @@ namespace currency
NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized<NOTIFY_REQUEST_CHAIN::request>();
m_core.get_short_chain_history(r.block_ids);
LOG_PRINT_MAGENTA("State changed to state_synchronizing.", LOG_LEVEL_2);
LOG_PRINT_L2("[REQUEST]NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_orphaned): m_block_ids.size()=" << r.block_ids.size() );
LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_orphaned): " << ENDL << print_kv_structure(r));
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
}
@ -355,6 +358,9 @@ namespace currency
template<class t_core>
int t_currency_protocol_handler<t_core>::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context)
{
LOG_PRINT_L2("[HANDLE]NOTIFY_REQUEST_GET_OBJECTS: arg.blocks.size() = " << arg.blocks.size() << ", arg.txs.size()="<< arg.txs.size());
LOG_PRINT_L3("[HANDLE]NOTIFY_REQUEST_GET_OBJECTS: " << ENDL << currency::print_kv_structure(arg));
if (arg.blocks.size() > CURRENCY_PROTOCOL_MAX_BLOCKS_REQUEST_COUNT)
{
LOG_ERROR_CCONTEXT("Requested objects count is to big (" << arg.blocks.size() <<")expected not more then " << CURRENCY_PROTOCOL_MAX_BLOCKS_REQUEST_COUNT);
@ -367,8 +373,12 @@ namespace currency
LOG_ERROR_CCONTEXT("failed to handle request NOTIFY_REQUEST_GET_OBJECTS, dropping connection");
m_p2p->drop_connection(context);
}
LOG_PRINT_L2("[HANDLE]NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()=" << rsp.blocks.size() << ", txs.size()=" << rsp.txs.size()
LOG_PRINT_L2("[NOTIFY]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());
LOG_PRINT_L3("[NOTIFY]NOTIFY_RESPONSE_GET_OBJECTS: " << ENDL << currency::print_kv_structure(rsp));
post_notify<NOTIFY_RESPONSE_GET_OBJECTS>(rsp, context);
return 1;
}
@ -383,12 +393,17 @@ namespace currency
}
return false;
}
#define CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(ret_v, msg) if (check_stop_flag_and_drop_cc(context)) { LOG_PRINT_YELLOW("Stop flag detected within NOTIFY_RESPONSE_GET_OBJECTS. " << msg, LOG_LEVEL_0); return ret_v; }
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
int t_currency_protocol_handler<t_core>::handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, currency_connection_context& context)
{
LOG_PRINT_L2("NOTIFY_RESPONSE_GET_OBJECTS");
LOG_PRINT_L2("[HANDLE]NOTIFY_RESPONSE_GET_OBJECTS: arg.blocks.size()=" << arg.blocks.size() << ", arg.missed_ids.size()=" << arg.missed_ids.size() << ", arg.txs.size()=" << arg.txs.size());
LOG_PRINT_L3("[HANDLE]NOTIFY_RESPONSE_GET_OBJECTS: " << ENDL << currency::print_kv_structure(arg));
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
@ -420,7 +435,7 @@ namespace currency
total_blocks_parsing_time += block_parsing_time;
//to avoid concurrency in core between connections, suspend connections which delivered block later then first one
if(count = 2)
if(count == 2)
{
if(m_core.have_block(get_block_hash(b)))
{
@ -511,7 +526,8 @@ namespace currency
}
if(bvc.m_marked_as_orphaned)
{
LOG_PRINT_L0("Block received at sync phase was marked as orphaned, dropping connection");
LOG_PRINT_L0("Block received at sync phase was marked as orphaned, dropping connection, details on response: " << ENDL << print_kv_structure(arg));
m_p2p->drop_connection(context);
m_p2p->add_ip_fail(context.m_remote_ip);
return 1;
@ -565,13 +581,16 @@ namespace currency
template<class t_core>
int t_currency_protocol_handler<t_core>::handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, currency_connection_context& context)
{
LOG_PRINT_L2("[HANDLE]NOTIFY_REQUEST_CHAIN: block_ids.size()=" << arg.block_ids.size());
LOG_PRINT_L3("[HANDLE]NOTIFY_REQUEST_CHAIN: " << print_kv_structure(arg));
NOTIFY_RESPONSE_CHAIN_ENTRY::request r;
if(!m_core.find_blockchain_supplement(arg.block_ids, r))
{
LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN.");
return 1;
}
LOG_PRINT_L2("[HANDLE]NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height=" << r.start_height << ", m_total_height=" << r.total_height << ", m_block_ids.size()=" << r.m_block_ids.size());
LOG_PRINT_L2("[NOTIFY]NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height=" << r.start_height << ", m_total_height=" << r.total_height << ", m_block_ids.size()=" << r.m_block_ids.size());
LOG_PRINT_L3("[NOTIFY]NOTIFY_RESPONSE_CHAIN_ENTRY: " << print_kv_structure(r));
post_notify<NOTIFY_RESPONSE_CHAIN_ENTRY>(r, context);
return 1;
}
@ -599,14 +618,16 @@ namespace currency
context.m_priv.m_needed_objects.erase(it++);
}
LOG_PRINT_L2("[REQUESTING]NOTIFY_REQUEST_GET_OBJECTS: requested_cumulative_size=" << requested_cumulative_size << ", blocks.size()=" << req.blocks.size() << ", txs.size()=" << req.txs.size());
LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_GET_OBJECTS(req_missing): requested_cumulative_size=" << requested_cumulative_size << ", blocks.size()=" << req.blocks.size() << ", txs.size()=" << req.txs.size());
LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_GET_OBJECTS(req_missing): " << ENDL << currency::print_kv_structure(req));
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);
LOG_PRINT_L2("[REQUESTING]NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_CHAIN: " << ENDL << print_kv_structure(r) );
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
}else
{
@ -620,7 +641,7 @@ namespace currency
<< "\r\non connection [" << net_utils::print_connection_context_short(context)<< "]");
context.m_state = currency_connection_context::state_normal;
LOG_PRINT_GREEN("[HANDLE]NOTIFY_REQUEST_GET_OBJECTS: SYNCHRONIZED OK", LOG_LEVEL_0);
LOG_PRINT_GREEN("[REQUEST_MISSING_OBJECTS]: SYNCHRONIZED OK", LOG_LEVEL_0);
on_connection_synchronized();
}
return true;
@ -725,8 +746,9 @@ namespace currency
template<class t_core>
int t_currency_protocol_handler<t_core>::handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, currency_connection_context& context)
{
LOG_PRINT_L2("NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()=" << arg.m_block_ids.size()
LOG_PRINT_L2("[HANDLE]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);
LOG_PRINT_L3("[HANDLE]NOTIFY_RESPONSE_CHAIN_ENTRY: " << ENDL << currency::print_kv_structure(arg));
if(!arg.m_block_ids.size())
{

View file

@ -124,6 +124,8 @@ namespace nodetool
HANDLE_INVOKE_T2(COMMAND_REQUEST_STAT_INFO, &node_server::handle_get_stat_info)
HANDLE_INVOKE_T2(COMMAND_REQUEST_NETWORK_STATE, &node_server::handle_get_network_state)
HANDLE_INVOKE_T2(COMMAND_REQUEST_PEER_ID, &node_server::handle_get_peer_id)
HANDLE_INVOKE_T2(COMMAND_REQUEST_LOG, &node_server::handle_request_log)
HANDLE_INVOKE_T2(COMMAND_SET_LOG_LEVEL, &node_server::handle_set_log_level)
#endif
CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(m_payload_handler, typename t_payload_net_handler::connection_context&)
END_INVOKE_MAP2()
@ -137,6 +139,8 @@ namespace nodetool
int handle_get_stat_info(int command, typename COMMAND_REQUEST_STAT_INFO::request& arg, typename COMMAND_REQUEST_STAT_INFO::response& rsp, p2p_connection_context& context);
int handle_get_network_state(int command, COMMAND_REQUEST_NETWORK_STATE::request& arg, COMMAND_REQUEST_NETWORK_STATE::response& rsp, p2p_connection_context& context);
int handle_get_peer_id(int command, COMMAND_REQUEST_PEER_ID::request& arg, COMMAND_REQUEST_PEER_ID::response& rsp, p2p_connection_context& context);
int handle_request_log(int command, COMMAND_REQUEST_LOG::request& arg, COMMAND_REQUEST_LOG::response& rsp, p2p_connection_context& context);
int handle_set_log_level(int command, COMMAND_SET_LOG_LEVEL::request& arg, COMMAND_SET_LOG_LEVEL::response& rsp, p2p_connection_context& context);
private:
#endif
bool init_config();

View file

@ -1039,6 +1039,7 @@ namespace nodetool
rsp.connections_count = m_net_server.get_config_object().get_connections_count();
rsp.incoming_connections_count = rsp.connections_count - get_outgoing_connections_count();
rsp.version = PROJECT_VERSION_LONG;
rsp.current_log_size = tools::get_log_file_size();
m_payload_handler.get_stat_info(arg.pr, rsp.payload_info);
return 1;
}
@ -1080,7 +1081,44 @@ namespace nodetool
rsp.my_id = m_config.m_peer_id;
return 1;
}
#endif
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_request_log(int command, COMMAND_REQUEST_LOG::request& req, COMMAND_REQUEST_LOG::response& rsp, p2p_connection_context& context)
{
if (!check_trust(req.tr))
{
drop_connection(context);
return 1;
}
rsp.current_log_level = static_cast<int64_t>(log_space::get_set_log_detalisation_level());
tools::get_log_chunk_gzipped(req.log_chunk_offset, req.log_chunk_size, rsp.log_chunk, rsp.error);
rsp.current_log_size = tools::get_log_file_size();
return 1;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_set_log_level(int command, COMMAND_SET_LOG_LEVEL::request& req, COMMAND_SET_LOG_LEVEL::response& rsp, p2p_connection_context& context)
{
if (!check_trust(req.tr))
{
drop_connection(context);
return 1;
}
rsp.old_log_level = static_cast<int64_t>(log_space::get_set_log_detalisation_level());
log_space::get_set_log_detalisation_level(true, static_cast<int>(req.new_log_level));
rsp.current_log_level = static_cast<int64_t>(log_space::get_set_log_detalisation_level());
if (rsp.old_log_level != rsp.current_log_level)
{
LOG_PRINT_CC(context, "log level changed by debug command: " << rsp.old_log_level << " -> " << rsp.current_log_level, LOG_LEVEL_0);
}
return 1;
}
#endif // #ifdef ALLOW_DEBUG_COMMANDS
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::request_callback(const epee::net_utils::connection_context_base& context)

View file

@ -328,12 +328,14 @@ namespace nodetool
std::string version;
uint64_t connections_count;
uint64_t incoming_connections_count;
uint64_t current_log_size;
payload_stat_info payload_info;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(version)
KV_SERIALIZE(connections_count)
KV_SERIALIZE(incoming_connections_count)
KV_SERIALIZE(current_log_size)
KV_SERIALIZE(payload_info)
END_KV_SERIALIZE_MAP()
};
@ -397,7 +399,73 @@ namespace nodetool
};
};
#endif
/************************************************************************/
/* */
/************************************************************************/
struct COMMAND_REQUEST_LOG
{
const static int ID = P2P_COMMANDS_POOL_BASE + 7;
struct request
{
proof_of_trust tr;
uint64_t log_chunk_offset;
uint64_t log_chunk_size;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tr)
KV_SERIALIZE(log_chunk_offset)
KV_SERIALIZE(log_chunk_size)
END_KV_SERIALIZE_MAP()
};
struct response
{
int64_t current_log_level;
uint64_t current_log_size;
std::string error;
std::string log_chunk;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(current_log_level)
KV_SERIALIZE(current_log_size)
KV_SERIALIZE(error)
KV_SERIALIZE(log_chunk)
END_KV_SERIALIZE_MAP()
};
};
/************************************************************************/
/* */
/************************************************************************/
struct COMMAND_SET_LOG_LEVEL
{
const static int ID = P2P_COMMANDS_POOL_BASE + 8;
struct request
{
proof_of_trust tr;
int64_t new_log_level;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tr)
KV_SERIALIZE(new_log_level)
END_KV_SERIALIZE_MAP()
};
struct response
{
int64_t old_log_level;
int64_t current_log_level;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(old_log_level)
KV_SERIALIZE(current_log_level)
END_KV_SERIALIZE_MAP()
};
};
#endif // #ifdef ALLOW_DEBUG_COMMANDS
}

View file

@ -35,9 +35,13 @@ int test_big_difficulties(const char* dataFile)
end = n - DIFFICULTY_LAG;
begin = end - DIFFICULTY_WINDOW;
}
auto stamps = vector<uint64_t>(timestamps.begin() + begin, timestamps.begin() + end);
auto cumulative_diffs = vector<currency::wide_difficulty_type>(cumulative_difficulties.begin() + begin, cumulative_difficulties.begin() + end);
currency::wide_difficulty_type res = currency::next_difficulty(
vector<uint64_t>(timestamps.begin() + begin, timestamps.begin() + end),
vector<currency::wide_difficulty_type>(cumulative_difficulties.begin() + begin, cumulative_difficulties.begin() + end), DEFAULT_TEST_DIFFICULTY_TARGET);
stamps,
cumulative_diffs,
DEFAULT_TEST_DIFFICULTY_TARGET
);
if (res != difficulty) {
cerr << "Wrong wide difficulty for block " << n << endl
<< "Expected: " << difficulty << endl
@ -90,9 +94,13 @@ int main(int argc, char *argv[]) {
<< "Found: " << res << endl;
return 1;
}
auto stamps = vector<uint64_t>(timestamps.begin() + begin, timestamps.begin() + end);
auto cumulative_diffs = vector<currency::wide_difficulty_type>(wide_cumulative_difficulties.begin() + begin, wide_cumulative_difficulties.begin() + end);
currency::wide_difficulty_type wide_res = currency::next_difficulty(
vector<uint64_t>(timestamps.begin() + begin, timestamps.begin() + end),
vector<currency::wide_difficulty_type>(wide_cumulative_difficulties.begin() + begin, wide_cumulative_difficulties.begin() + end), DEFAULT_TEST_DIFFICULTY_TARGET);
stamps,
cumulative_diffs,
DEFAULT_TEST_DIFFICULTY_TARGET
);
if (wide_res.convert_to<uint64_t>() != res) {
cerr << "Wrong wide difficulty for block " << n << endl
<< "Expected: " << res << endl
@ -110,3 +118,4 @@ int main(int argc, char *argv[]) {
return 0;
}

View file

@ -147,16 +147,16 @@ currency::wide_difficulty_type bbr_next_difficulty_configurable(std::vector<uint
return res.convert_to<currency::wide_difficulty_type>();
}
currency::wide_difficulty_type bbr_next_difficulty_composit(std::vector<uint64_t>& timestamps, std::vector<currency::wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, size_t REDEF_DIFFICULTY_WINDOW, size_t REDEF_DIFFICULTY_CUT_OLD, size_t REDEF_DIFFICULTY_CUT_LAST)
{
sort(timestamps.begin(), timestamps.end(), std::greater<uint64_t>());
std::vector<uint64_t> timestamps_local = timestamps;
currency::wide_difficulty_type dif = bbr_next_difficulty_configurable(timestamps_local, cumulative_difficulties, target_seconds, REDEF_DIFFICULTY_WINDOW, REDEF_DIFFICULTY_CUT_OLD, REDEF_DIFFICULTY_CUT_LAST);
currency::wide_difficulty_type dif2 = bbr_next_difficulty_configurable(timestamps_local, cumulative_difficulties, target_seconds, 300, 20, 5);
if (dif < dif2)
return dif;
else
return dif2;
currency::wide_difficulty_type dif2 = bbr_next_difficulty_configurable(timestamps_local, cumulative_difficulties, target_seconds, 200, 5, 5);
currency::wide_difficulty_type dif3 = bbr_next_difficulty_configurable(timestamps_local, cumulative_difficulties, target_seconds, 40, 1, 1);
return (dif3 + dif2 + dif) / 3;
}
currency::wide_difficulty_type bbr_next_difficulty2(std::vector<uint64_t>& timestamps, std::vector<currency::wide_difficulty_type>& cumulative_difficulties, size_t target_seconds)
@ -202,7 +202,7 @@ uint64_t get_hashrate_by_timestamp(const std::map<uint64_t, uint64_t> timestamp_
return 0;
}
return (--it)->second;
return (--it)->second;;
}
@ -252,6 +252,12 @@ void perform_simulation_for_function(const std::map<uint64_t, uint64_t>& timesta
index_in_result_blocks++;
std::cout << index_in_result_blocks << "\r";
}
if (index_in_result_blocks < 410)
{
for (size_t k = index_in_result_blocks; k != 410; k++)
result_blocks[k][index_in_result] = result_blocks[k-1][index_in_result];
}
std::cout << "\n";
}