diff options
Diffstat (limited to 'src')
46 files changed, 486 insertions, 276 deletions
diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 873bf552c..24a750eb0 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -26,6 +26,20 @@ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +set(blocksdat "") +if(PER_BLOCK_CHECKPOINT) + if(APPLE AND DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(APPLE AND NOT DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(LINUX_32) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + else() + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + endif() + set(blocksdat "blocksdat.o") +endif() + set(blockchain_import_sources blockchain_import.cpp bootstrap_file.cpp @@ -105,7 +119,8 @@ monero_private_headers(blockchain_depth monero_add_executable(blockchain_import ${blockchain_import_sources} - ${blockchain_import_private_headers}) + ${blockchain_import_private_headers} + ${blocksdat}) target_link_libraries(blockchain_import PRIVATE @@ -117,8 +132,7 @@ target_link_libraries(blockchain_import ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES} - ${Blocks}) + ${EXTRA_LIBRARIES}) if(ARCH_WIDTH) target_compile_definitions(blockchain_import @@ -170,7 +184,7 @@ target_link_libraries(blockchain_blackball set_property(TARGET blockchain_blackball PROPERTY - OUTPUT_NAME "monero-blockchain-blackball") + OUTPUT_NAME "monero-blockchain-mark-spent-outputs") install(TARGETS blockchain_blackball DESTINATION bin) diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 5eb2acc79..d2ce5cf76 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -226,7 +226,7 @@ static void init(std::string cache_filename) bool tx_active = false; int dbr; - MINFO("Creating blackball cache in " << cache_filename); + MINFO("Creating spent output cache in " << cache_filename); tools::create_directories_if_necessary(cache_filename); @@ -536,12 +536,15 @@ static uint64_t get_num_spent_outputs() return count; } -static void add_spent_output(MDB_cursor *cur, const output_data &od) +static bool add_spent_output(MDB_cursor *cur, const output_data &od) { MDB_val k = {sizeof(od.amount), (void*)&od.amount}; MDB_val v = {sizeof(od.offset), (void*)&od.offset}; - int dbr = mdb_cursor_put(cur, &k, &v, 0); - CHECK_AND_ASSERT_THROW_MES(!dbr || dbr == MDB_KEYEXIST, "Failed to add spent output: " + std::string(mdb_strerror(dbr))); + int dbr = mdb_cursor_put(cur, &k, &v, MDB_NODUPDATA); + if (dbr == MDB_KEYEXIST) + return false; + CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to add spent output: " + std::string(mdb_strerror(dbr))); + return true; } static bool is_output_spent(MDB_cursor *cur, const output_data &od) @@ -1016,7 +1019,7 @@ int main(int argc, char* argv[]) po::options_description desc_cmd_only("Command line options"); po::options_description desc_cmd_sett("Command line options and settings options"); const command_line::arg_descriptor<std::string> arg_blackball_db_dir = { - "blackball-db-dir", "Specify blackball database directory", + "spent-output-db-dir", "Specify spent output database directory", get_default_db_path(), }; const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""}; @@ -1073,7 +1076,7 @@ int main(int argc, char* argv[]) return 1; } - mlog_configure(mlog_get_default_log_path("monero-blockchain-blackball.log"), true); + mlog_configure(mlog_get_default_log_path("monero-blockchain-find-spent-outputs.log"), true); if (!command_line::is_arg_defaulted(vm, arg_log_level)) mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); else @@ -1111,10 +1114,10 @@ int main(int argc, char* argv[]) return 1; } - const std::string cache_dir = (output_file_path / "blackball-cache").string(); + const std::string cache_dir = (output_file_path / "spent-outputs-cache").string(); init(cache_dir); - LOG_PRINT_L0("Scanning for blackballable outputs..."); + LOG_PRINT_L0("Scanning for spent outputs..."); size_t done = 0; @@ -1153,8 +1156,8 @@ int main(int argc, char* argv[]) if (!is_output_spent(cur, output_data(output.first, output.second))) { blackballs.push_back(output); - add_spent_output(cur, output_data(output.first, output.second)); - inc_stat(txn, output.first ? "pre-rct-extra" : "rct-ring-extra"); + if (add_spent_output(cur, output_data(output.first, output.second))) + inc_stat(txn, output.first ? "pre-rct-extra" : "rct-ring-extra"); } } if (!blackballs.empty()) @@ -1212,12 +1215,12 @@ int main(int argc, char* argv[]) const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[0]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a 1-ring"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a 1-ring"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, absolute[0])); - inc_stat(txn, txin.amount ? "pre-rct-ring-size-1" : "rct-ring-size-1"); + if (add_spent_output(cur, output_data(txin.amount, absolute[0]))) + inc_stat(txn, txin.amount ? "pre-rct-ring-size-1" : "rct-ring-size-1"); } else if (n == 0 && instances == new_ring.size()) { @@ -1226,12 +1229,12 @@ int main(int argc, char* argv[]) const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[o]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, absolute[o])); - inc_stat(txn, txin.amount ? "pre-rct-duplicate-rings" : "rct-duplicate-rings"); + if (add_spent_output(cur, output_data(txin.amount, absolute[o]))) + inc_stat(txn, txin.amount ? "pre-rct-duplicate-rings" : "rct-duplicate-rings"); } } else if (n == 0 && opt_check_subsets && get_ring_subset_instances(txn, txin.amount, new_ring) >= new_ring.size()) @@ -1241,12 +1244,12 @@ int main(int argc, char* argv[]) const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[o]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, absolute[o])); - inc_stat(txn, txin.amount ? "pre-rct-subset-rings" : "rct-subset-rings"); + if (add_spent_output(cur, output_data(txin.amount, absolute[o]))) + inc_stat(txn, txin.amount ? "pre-rct-subset-rings" : "rct-subset-rings"); } } else if (n > 0 && get_relative_ring(txn, txin.k_image, relative_ring)) @@ -1277,12 +1280,12 @@ int main(int argc, char* argv[]) const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, common[0]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in rings with a single common element"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in rings with a single common element"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, common[0])); - inc_stat(txn, txin.amount ? "pre-rct-key-image-attack" : "rct-key-image-attack"); + if (add_spent_output(cur, output_data(txin.amount, common[0]))) + inc_stat(txn, txin.amount ? "pre-rct-key-image-attack" : "rct-key-image-attack"); } else { @@ -1389,13 +1392,13 @@ int main(int argc, char* argv[]) const std::pair<uint64_t, uint64_t> output = std::make_pair(od.amount, last_unknown); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a " << + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a " << absolute.size() << "-ring where all other outputs are known to be spent"); } blackballs.push_back(output); - add_spent_output(cur, output_data(od.amount, last_unknown)); + if (add_spent_output(cur, output_data(od.amount, last_unknown))) + inc_stat(txn, od.amount ? "pre-rct-chain-reaction" : "rct-chain-reaction"); work_spent.push_back(output_data(od.amount, last_unknown)); - inc_stat(txn, od.amount ? "pre-rct-chain-reaction" : "rct-chain-reaction"); } } @@ -1417,7 +1420,7 @@ int main(int argc, char* argv[]) skip_secondary_passes: uint64_t diff = get_num_spent_outputs() - start_blackballed_outputs; - LOG_PRINT_L0(std::to_string(diff) << " new outputs blackballed, " << get_num_spent_outputs() << " total outputs blackballed"); + LOG_PRINT_L0(std::to_string(diff) << " new outputs marked as spent, " << get_num_spent_outputs() << " total outputs marked as spent"); MDB_txn *txn; dbr = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); @@ -1457,7 +1460,7 @@ skip_secondary_passes: mdb_txn_abort(txn); } - LOG_PRINT_L0("Blockchain blackball data exported OK"); + LOG_PRINT_L0("Blockchain spent output data exported OK"); close_db(env0, txn0, cur0, dbi0); close(); return 0; diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 134969dc4..9ec768d26 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -37,7 +37,6 @@ #include "misc_log_ex.h" #include "bootstrap_file.h" #include "bootstrap_serialization.h" -#include "blocks/blocks.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "serialization/binary_utils.h" // dump_binary(), parse_binary() #include "serialization/json_utils.h" // dump_json() @@ -759,12 +758,7 @@ int main(int argc, char* argv[]) { core.disable_dns_checkpoints(true); -#if defined(PER_BLOCK_CHECKPOINT) - GetCheckpointsCallback get_checkpoints = blocks::GetCheckpointsData; -#else - GetCheckpointsCallback get_checkpoints = nullptr; -#endif - if (!core.init(vm, nullptr, nullptr, get_checkpoints)) + if (!core.init(vm, NULL)) { std::cerr << "Failed to initialize core" << ENDL; return 1; diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index bedda3b88..ebb5408cc 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -26,23 +26,20 @@ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set(GENERATED_SOURCES "") +if(APPLE) + add_library(blocks STATIC blockexports.c) + set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) +else() + if(LINUX_32) + add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) + add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + else() + add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) + add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + endif() + add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c) + set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) +endif() -foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks) - set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c") - list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE}) - set(INPUT_DAT_FILE "${BLOB_NAME}.dat") - add_custom_command( - OUTPUT ${OUTPUT_C_SOURCE} - MAIN_DEPENDENCY ${INPUT_DAT_FILE} - COMMAND - cd ${CMAKE_CURRENT_BINARY_DIR} && - echo "'#include\t<stddef.h>'" > ${OUTPUT_C_SOURCE} && - echo -n "'const\tunsigned\tchar\t${BLOB_NAME}[]={'" >> ${OUTPUT_C_SOURCE} && - od -v -An -w1 -tu1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "':a;N;$$!ba;s/\\n/,/g'" >> ${OUTPUT_C_SOURCE} && - echo "'};'" >> ${OUTPUT_C_SOURCE} && - echo "'const\tsize_t\t${BLOB_NAME}_len\t=\tsizeof(${BLOB_NAME});'" >> ${OUTPUT_C_SOURCE} - ) -endforeach() - -add_library(blocks STATIC blocks.cpp ${GENERATED_SOURCES}) diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c new file mode 100644 index 000000000..0154b0413 --- /dev/null +++ b/src/blocks/blockexports.c @@ -0,0 +1,87 @@ +#include <stddef.h> + +#if defined(__APPLE__) +#include <mach-o/getsect.h> +#ifdef BUILD_SHARED_LIBS +#if !defined(__LP64__) +const struct mach_header _mh_execute_header; +#else +const struct mach_header_64 _mh_execute_header; +#endif +#else +#if !defined(__LP64__) +extern const struct mach_header _mh_execute_header; +#else +extern const struct mach_header_64 _mh_execute_header; +#endif +#endif + +const unsigned char *get_blocks_dat_start(int testnet, int stagenet) +{ + size_t size; + if (testnet) + return getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); + else if (stagenet) + return getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); + else + return getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); +} + +size_t get_blocks_dat_size(int testnet, int stagenet) +{ + size_t size; + if (testnet) + getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); + else if (stagenet) + getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); + else + getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); + return size; +} + +#else + +#if defined(_WIN32) && !defined(_WIN64) +#define _binary_blocks_start binary_blocks_dat_start +#define _binary_blocks_end binary_blocks_dat_end +#define _binary_testnet_blocks_start binary_testnet_blocks_dat_start +#define _binary_testnet_blocks_end binary_testnet_blocks_dat_end +#define _binary_stagenet_blocks_start binary_stagenet_blocks_dat_start +#define _binary_stagenet_blocks_end binary_stagenet_blocks_dat_end +#else +#define _binary_blocks_start _binary_blocks_dat_start +#define _binary_blocks_end _binary_blocks_dat_end +#define _binary_testnet_blocks_start _binary_testnet_blocks_dat_start +#define _binary_testnet_blocks_end _binary_testnet_blocks_dat_end +#define _binary_stagenet_blocks_start _binary_stagenet_blocks_dat_start +#define _binary_stagenet_blocks_end _binary_stagenet_blocks_dat_end +#endif + +extern const unsigned char _binary_blocks_start[]; +extern const unsigned char _binary_blocks_end[]; +extern const unsigned char _binary_testnet_blocks_start[]; +extern const unsigned char _binary_testnet_blocks_end[]; +extern const unsigned char _binary_stagenet_blocks_start[]; +extern const unsigned char _binary_stagenet_blocks_end[]; + +const unsigned char *get_blocks_dat_start(int testnet, int stagenet) +{ + if (testnet) + return _binary_testnet_blocks_start; + else if (stagenet) + return _binary_stagenet_blocks_start; + else + return _binary_blocks_start; +} + +size_t get_blocks_dat_size(int testnet, int stagenet) +{ + if (testnet) + return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start); + else if (stagenet) + return (size_t) (_binary_stagenet_blocks_end - _binary_stagenet_blocks_start); + else + return (size_t) (_binary_blocks_end - _binary_blocks_start); +} + +#endif diff --git a/src/blocks/blocks.cpp b/src/blocks/blocks.cpp deleted file mode 100644 index 0661f8448..000000000 --- a/src/blocks/blocks.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "blocks.h" - -#include <unordered_map> - -extern const unsigned char checkpoints[]; -extern const size_t checkpoints_len; -extern const unsigned char stagenet_blocks[]; -extern const size_t stagenet_blocks_len; -extern const unsigned char testnet_blocks[]; -extern const size_t testnet_blocks_len; - -namespace blocks -{ - - const std::unordered_map<cryptonote::network_type, const epee::span<const unsigned char>, std::hash<size_t>> CheckpointsByNetwork = { - {cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}}, - {cryptonote::network_type::STAGENET, {stagenet_blocks, stagenet_blocks_len}}, - {cryptonote::network_type::TESTNET, {testnet_blocks, testnet_blocks_len}} - }; - - const epee::span<const unsigned char> GetCheckpointsData(cryptonote::network_type network) - { - const auto it = CheckpointsByNetwork.find(network); - if (it != CheckpointsByNetwork.end()) - { - return it->second; - } - return nullptr; - } - -} diff --git a/src/blocks/blocks.dat b/src/blocks/blocks.dat new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/blocks/blocks.dat diff --git a/src/blocks/blocks.h b/src/blocks/blocks.h index 14e391319..ec683f47e 100644 --- a/src/blocks/blocks.h +++ b/src/blocks/blocks.h @@ -1,12 +1,16 @@ #ifndef SRC_BLOCKS_BLOCKS_H_ #define SRC_BLOCKS_BLOCKS_H_ -#include "cryptonote_config.h" -#include "span.h" +#ifdef __cplusplus +extern "C" { +#endif -namespace blocks -{ - const epee::span<const unsigned char> GetCheckpointsData(cryptonote::network_type network); +const unsigned char *get_blocks_dat_start(int testnet, int stagenet); +size_t get_blocks_dat_size(int testnet, int stagenet); + +#ifdef __cplusplus } +#endif + #endif /* SRC_BLOCKS_BLOCKS_H_ */ diff --git a/src/common/expect.h b/src/common/expect.h index 326242502..72e4060a7 100644 --- a/src/common/expect.h +++ b/src/common/expect.h @@ -350,7 +350,9 @@ public: using error_type = std::error_code; //! Create a successful object. - expect() = default; + expect() noexcept + : code_() + {} expect(std::error_code const& code) noexcept : code_(code) diff --git a/src/common/password.cpp b/src/common/password.cpp index a8d5141dc..b3c51128f 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -60,7 +60,7 @@ namespace DWORD mode_old; ::GetConsoleMode(h_cin, &mode_old); - DWORD mode_new = mode_old & ~((hide_input ? ENABLE_ECHO_INPUT : 0) | ENABLE_LINE_INPUT); + DWORD mode_new = mode_old & ~(hide_input ? ENABLE_ECHO_INPUT : 0); ::SetConsoleMode(h_cin, mode_new); bool r = true; @@ -78,7 +78,11 @@ namespace { break; } - else if (ucs2_ch == L'\n' || ucs2_ch == L'\r') + else if (ucs2_ch == L'\r') + { + continue; + } + else if (ucs2_ch == L'\n') { std::cout << std::endl; break; @@ -158,6 +162,13 @@ namespace if (!aPass.empty()) { aPass.pop_back(); + if (!hide_input) + std::cout << "\b\b\b \b\b\b" << std::flush; + } + else + { + if (!hide_input) + std::cout << "\b\b \b\b" << std::flush; } } else diff --git a/src/common/spawn.cpp b/src/common/spawn.cpp index 59f11675c..0a2ce8387 100644 --- a/src/common/spawn.cpp +++ b/src/common/spawn.cpp @@ -38,6 +38,7 @@ #endif #include "misc_log_ex.h" +#include "util.h" #include "spawn.h" namespace tools @@ -101,6 +102,8 @@ int spawn(const char *filename, const std::vector<std::string>& args, bool wait) // child if (pid == 0) { + tools::closefrom(3); + close(0); char *envp[] = {NULL}; execve(filename, argv, envp); MERROR("Failed to execve: " << strerror(errno)); diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index 5ea04a353..37825e31d 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -51,11 +51,19 @@ threadpool::threadpool(unsigned int max_threads) : running(true), active(0) { } threadpool::~threadpool() { + try { const boost::unique_lock<boost::mutex> lock(mutex); running = false; has_work.notify_all(); } + catch (...) + { + // if the lock throws, we're just do it without a lock and hope, + // since the alternative is terminate + running = false; + has_work.notify_all(); + } for (size_t i = 0; i<threads.size(); i++) { try { threads[i].join(); } catch (...) { /* ignore */ } @@ -91,11 +99,13 @@ unsigned int threadpool::get_max_concurrency() const { threadpool::waiter::~waiter() { + try { boost::unique_lock<boost::mutex> lock(mt); if (num) MERROR("wait should have been called before waiter dtor - waiting now"); } + catch (...) { /* ignore */ } try { wait(NULL); diff --git a/src/common/util.cpp b/src/common/util.cpp index 2a1d49af0..f91230528 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -28,6 +28,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#include <unistd.h> #include <cstdio> #ifdef __GLIBC__ @@ -233,7 +234,7 @@ namespace tools MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category())); } #else - m_fd = open(filename.c_str(), O_RDONLY | O_CREAT, 0666); + m_fd = open(filename.c_str(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666); if (m_fd != -1) { if (flock(m_fd, LOCK_EX | LOCK_NB) == -1) @@ -967,4 +968,23 @@ std::string get_nix_version_display_string() } #endif + void closefrom(int fd) + { +#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__ + ::closefrom(fd); +#else +#if defined __GLIBC__ + const int sc_open_max = sysconf(_SC_OPEN_MAX); + const int MAX_FDS = std::min(65536, sc_open_max); +#else + const int MAX_FDS = 65536; +#endif + while (fd < MAX_FDS) + { + close(fd); + ++fd; + } +#endif + } + } diff --git a/src/common/util.h b/src/common/util.h index ce773bd38..e793a42b5 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -238,4 +238,6 @@ namespace tools #ifdef _WIN32 std::string input_line_win(); #endif + + void closefrom(int fd); } diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 5fcfa33f6..9e9c12605 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -199,6 +199,16 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx) + { + std::stringstream ss; + ss << tx_blob; + binary_archive<false> ba(ss); + bool r = ::serialization::serialize_noeof(ba, tx); + CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction prefix from blob"); + return true; + } + //--------------------------------------------------------------- bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash) { std::stringstream ss; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index bf71eb591..725c75f4e 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -48,6 +48,7 @@ namespace cryptonote //--------------------------------------------------------------- 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_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx); diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 2bd43de94..d0b03593e 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -201,7 +201,7 @@ namespace cryptonote float hr = static_cast<float>(total_hr)/static_cast<float>(m_last_hash_rates.size()); const auto flags = std::cout.flags(); const auto precision = std::cout.precision(); - std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << flags << precision << ENDL; + std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << std::setiosflags(flags) << std::setprecision(precision) << ENDL; } } m_last_hr_merge_time = misc_utils::get_tick_count(); diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index c62eeb738..a6858ce7c 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -30,7 +30,6 @@ #pragma once -#include <stdexcept> #include <string> #include <boost/uuid/uuid.hpp> diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 231489fdb..72844db66 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -41,6 +41,12 @@ set(cryptonote_core_private_headers tx_pool.h cryptonote_tx_utils.h) +if(PER_BLOCK_CHECKPOINT) + set(Blocks "blocks") +else() + set(Blocks "") +endif() + monero_private_headers(cryptonote_core ${cryptonote_core_private_headers}) monero_add_library(cryptonote_core @@ -63,4 +69,5 @@ target_link_libraries(cryptonote_core ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} PRIVATE + ${Blocks} ${EXTRA_LIBRARIES}) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 6c6e024e4..1ec2366e4 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -53,6 +53,9 @@ #include "ringct/rctSigs.h" #include "common/perf_timer.h" #include "common/notify.h" +#if defined(PER_BLOCK_CHECKPOINT) +#include "blocks/blocks.h" +#endif #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "blockchain" @@ -338,9 +341,12 @@ uint64_t Blockchain::get_current_blockchain_height() const //------------------------------------------------------------------ //FIXME: possibly move this into the constructor, to avoid accidentally // dereferencing a null BlockchainDB pointer -bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty, const GetCheckpointsCallback get_checkpoints/* = nullptr*/) +bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty) { LOG_PRINT_L3("Blockchain::" << __func__); + + CHECK_AND_ASSERT_MES(nettype != FAKECHAIN || test_options, false, "fake chain network type used without options"); + CRITICAL_REGION_LOCAL(m_tx_pool); CRITICAL_REGION_LOCAL1(m_blockchain_lock); @@ -436,7 +442,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline #if defined(PER_BLOCK_CHECKPOINT) if (m_nettype != FAKECHAIN) - load_compiled_in_block_hashes(get_checkpoints); + load_compiled_in_block_hashes(); #endif MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block()); @@ -2361,7 +2367,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type); if (bulletproof || !tx.rct_signatures.p.bulletproofs.empty()) { - MERROR("Bulletproofs are not allowed before v8"); + MERROR_VER("Bulletproofs are not allowed before v8"); tvc.m_invalid_output = true; return false; } @@ -2374,7 +2380,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context const bool borromean = rct::is_rct_borromean(tx.rct_signatures.type); if (borromean) { - MERROR("Borromean range proofs are not allowed after v8"); + MERROR_VER("Borromean range proofs are not allowed after v8"); tvc.m_invalid_output = true; return false; } @@ -4401,21 +4407,19 @@ void Blockchain::cancel() #if defined(PER_BLOCK_CHECKPOINT) static const char expected_block_hashes_hash[] = "954cb2bbfa2fe6f74b2cdd22a1a4c767aea249ad47ad4f7c9445f0f03260f511"; -void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback get_checkpoints) +void Blockchain::load_compiled_in_block_hashes() { - if (get_checkpoints == nullptr || !m_fast_sync) + const bool testnet = m_nettype == TESTNET; + const bool stagenet = m_nettype == STAGENET; + if (m_fast_sync && get_blocks_dat_start(testnet, stagenet) != nullptr && get_blocks_dat_size(testnet, stagenet) > 0) { - return; - } - const epee::span<const unsigned char> checkpoints = get_checkpoints(m_nettype); - if (!checkpoints.empty()) - { - MINFO("Loading precomputed blocks (" << checkpoints.size() << " bytes)"); + MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)"); + if (m_nettype == MAINNET) { // first check hash crypto::hash hash; - if (!tools::sha256sum(checkpoints.data(), checkpoints.size(), hash)) + if (!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash)) { MERROR("Failed to hash precomputed blocks data"); return; @@ -4435,9 +4439,9 @@ void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback get_ } } - if (checkpoints.size() > 4) + if (get_blocks_dat_size(testnet, stagenet) > 4) { - const unsigned char *p = checkpoints.data(); + const unsigned char *p = get_blocks_dat_start(testnet, stagenet); const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24); if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) / sizeof(hash)) { @@ -4445,7 +4449,7 @@ void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback get_ return; } const size_t size_needed = 4 + nblocks * sizeof(crypto::hash); - if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && checkpoints.size() >= size_needed) + if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(testnet, stagenet) >= size_needed) { p += sizeof(uint32_t); m_blocks_hash_of_hashes.reserve(nblocks); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 9b67765b5..ab66fac8b 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -38,11 +38,9 @@ #include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/member.hpp> #include <atomic> -#include <functional> #include <unordered_map> #include <unordered_set> -#include "span.h" #include "syncobj.h" #include "string_tools.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -75,15 +73,6 @@ namespace cryptonote db_nosync //!< Leave syncing up to the backing db (safest, but slowest because of disk I/O) }; - /** - * @brief Callback routine that returns checkpoints data for specific network type - * - * @param network network type - * - * @return checkpoints data, empty span if there ain't any checkpoints for specific network type - */ - typedef std::function<const epee::span<const unsigned char>(cryptonote::network_type network)> GetCheckpointsCallback; - /************************************************************************/ /* */ /************************************************************************/ @@ -128,11 +117,10 @@ namespace cryptonote * @param offline true if running offline, else false * @param test_options test parameters * @param fixed_difficulty fixed difficulty for testing purposes; 0 means disabled - * @param get_checkpoints if set, will be called to get checkpoints data * * @return true on success, false if any initialization steps fail */ - bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0, const GetCheckpointsCallback get_checkpoints = nullptr); + bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0); /** * @brief Initialize the Blockchain state @@ -1381,10 +1369,8 @@ namespace cryptonote * A (possibly empty) set of block hashes can be compiled into the * monero daemon binary. This function loads those hashes into * a useful state. - * - * @param get_checkpoints if set, will be called to get checkpoints data */ - void load_compiled_in_block_hashes(const GetCheckpointsCallback get_checkpoints); + void load_compiled_in_block_hashes(); /** * @brief expands v2 transaction data from blockchain diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 3882a14ae..2fec6b613 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -389,7 +389,7 @@ namespace cryptonote return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options, const GetCheckpointsCallback get_checkpoints/* = nullptr */) + bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options) { start_time = std::time(nullptr); @@ -567,7 +567,7 @@ namespace cryptonote regtest_hard_forks }; const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty); - r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty, get_checkpoints); + r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty); r = m_mempool.init(max_txpool_weight); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); @@ -856,16 +856,19 @@ namespace cryptonote } waiter.wait(&tpool); it = tx_blobs.begin(); + std::vector<bool> already_have(tx_blobs.size(), false); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { if (!results[i].res) continue; if(m_mempool.have_tx(results[i].hash)) { LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool"); + already_have[i] = true; } else if(m_blockchain_storage.have_tx(results[i].hash)) { LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain"); + already_have[i] = true; } else { @@ -887,7 +890,7 @@ namespace cryptonote std::vector<tx_verification_batch_info> tx_info; tx_info.reserve(tx_blobs.size()); for (size_t i = 0; i < tx_blobs.size(); i++) { - if (!results[i].res) + if (!results[i].res || already_have[i]) continue; tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res}); } @@ -897,6 +900,8 @@ namespace cryptonote bool ok = true; it = tx_blobs.begin(); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { + if (already_have[i]) + continue; if (!results[i].res) { ok = false; diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 882568330..58fe5b7b5 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -244,11 +244,10 @@ namespace cryptonote * @param vm command line parameters * @param config_subdir subdirectory for config storage * @param test_options configuration options for testing - * @param get_checkpoints if set, will be called to get checkpoints data, must return checkpoints data pointer and size or nullptr if there ain't any checkpoints for specific network type * * @return false if one of the init steps fails, otherwise true */ - bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL, const GetCheckpointsCallback get_checkpoints = nullptr); + bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL); /** * @copydoc Blockchain::reset_and_set_genesis_block diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index c31a2073b..553a22298 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -250,7 +250,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); m_blockchain.add_txpool_tx(tx, meta); - if (!insert_key_images(tx, kept_by_block)) + if (!insert_key_images(tx, id, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id); } @@ -290,9 +290,10 @@ namespace cryptonote { CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); - m_blockchain.remove_txpool_tx(get_transaction_hash(tx)); + const crypto::hash txid = get_transaction_hash(tx); + m_blockchain.remove_txpool_tx(txid); m_blockchain.add_txpool_tx(tx, meta); - if (!insert_key_images(tx, kept_by_block)) + if (!insert_key_images(tx, txid, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id); } @@ -371,8 +372,8 @@ namespace cryptonote continue; } cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid); - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(txblob, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(txblob, tx)) { MERROR("Failed to parse tx from txpool"); return; @@ -381,7 +382,7 @@ namespace cryptonote MINFO("Pruning tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first); m_blockchain.remove_txpool_tx(txid); m_txpool_weight -= it->first.second; - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, txid); MINFO("Pruned tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first); m_txs_by_fee_and_receive_time.erase(it--); changed = true; @@ -398,11 +399,10 @@ namespace cryptonote MINFO("Pool weight after pruning is larger than limit: " << m_txpool_weight << "/" << bytes); } //--------------------------------------------------------------------------------- - bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block) + bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block) { for(const auto& in: tx.vin) { - const crypto::hash id = get_transaction_hash(tx); CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, txin, false); std::unordered_set<crypto::hash>& kei_image_set = m_spent_key_images[txin.k_image]; CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block @@ -418,19 +418,17 @@ namespace cryptonote //FIXME: Can return early before removal of all of the key images. // At the least, need to make sure that a false return here // is treated properly. Should probably not return early, however. - bool tx_memory_pool::remove_transaction_keyimages(const transaction& tx) + bool tx_memory_pool::remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &actual_hash) { CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); // ND: Speedup - // 1. Move transaction hash calcuation outside of loop. ._. - crypto::hash actual_hash = get_transaction_hash(tx); for(const txin_v& vi: tx.vin) { CHECKED_GET_SPECIFIC_VARIANT(vi, const txin_to_key, txin, false); auto it = m_spent_key_images.find(txin.k_image); CHECK_AND_ASSERT_MES(it != m_spent_key_images.end(), false, "failed to find transaction input in key images. img=" << txin.k_image << ENDL - << "transaction id = " << get_transaction_hash(tx)); + << "transaction id = " << actual_hash); std::unordered_set<crypto::hash>& key_image_set = it->second; CHECK_AND_ASSERT_MES(key_image_set.size(), false, "empty key_image set, img=" << txin.k_image << ENDL << "transaction id = " << actual_hash); @@ -483,7 +481,7 @@ namespace cryptonote // remove first, in case this throws, so key images aren't removed m_blockchain.remove_txpool_tx(id); m_txpool_weight -= tx_weight; - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, id); } catch (const std::exception &e) { @@ -515,7 +513,7 @@ namespace cryptonote { CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); - std::unordered_set<crypto::hash> remove; + std::list<std::pair<crypto::hash, uint64_t>> remove; m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) { uint64_t tx_age = time(nullptr) - meta.receive_time; @@ -533,7 +531,7 @@ namespace cryptonote m_txs_by_fee_and_receive_time.erase(sorted_it); } m_timed_out_transactions.insert(txid); - remove.insert(txid); + remove.push_back(std::make_pair(txid, meta.weight)); } return true; }, false); @@ -541,13 +539,14 @@ namespace cryptonote if (!remove.empty()) { LockedTXN lock(m_blockchain); - for (const crypto::hash &txid: remove) + for (const std::pair<crypto::hash, uint64_t> &entry: remove) { + const crypto::hash &txid = entry.first; try { cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid); - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(bd, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(bd, tx)) { MERROR("Failed to parse tx from txpool"); // continue @@ -556,8 +555,8 @@ namespace cryptonote { // remove first, so we only remove key images if the tx removal succeeds m_blockchain.remove_txpool_tx(txid); - m_txpool_weight -= get_transaction_weight(tx, bd.size()); - remove_transaction_keyimages(tx); + m_txpool_weight -= entry.second; + remove_transaction_keyimages(tx, txid); } } catch (const std::exception &e) @@ -1041,7 +1040,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- - bool tx_memory_pool::have_key_images(const std::unordered_set<crypto::key_image>& k_images, const transaction& tx) + bool tx_memory_pool::have_key_images(const std::unordered_set<crypto::key_image>& k_images, const transaction_prefix& tx) { for(size_t i = 0; i!= tx.vin.size(); i++) { @@ -1052,7 +1051,7 @@ namespace cryptonote return false; } //--------------------------------------------------------------------------------- - bool tx_memory_pool::append_key_images(std::unordered_set<crypto::key_image>& k_images, const transaction& tx) + bool tx_memory_pool::append_key_images(std::unordered_set<crypto::key_image>& k_images, const transaction_prefix& tx) { for(size_t i = 0; i!= tx.vin.size(); i++) { @@ -1301,7 +1300,7 @@ namespace cryptonote // remove tx from db first m_blockchain.remove_txpool_tx(txid); m_txpool_weight -= get_transaction_weight(tx, txblob.size()); - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, txid); auto sorted_it = find_tx_in_sorted_container(txid); if (sorted_it == m_txs_by_fee_and_receive_time.end()) { @@ -1344,14 +1343,14 @@ namespace cryptonote bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) { if (!!kept != !!meta.kept_by_block) return true; - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(*bd, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(*bd, tx)) { MWARNING("Failed to parse tx from txpool, removing"); remove.push_back(txid); return true; } - if (!insert_key_images(tx, meta.kept_by_block)) + if (!insert_key_images(tx, txid, meta.kept_by_block)) { MFATAL("Failed to insert key images from txpool tx"); return false; diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 892cadc69..7a0cc23bf 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -434,7 +434,7 @@ namespace cryptonote * * @return true on success, false on error */ - bool insert_key_images(const transaction &tx, bool kept_by_block); + bool insert_key_images(const transaction_prefix &tx, const crypto::hash &txid, bool kept_by_block); /** * @brief remove old transactions from the pool @@ -478,10 +478,11 @@ namespace cryptonote * a transaction from the pool. * * @param tx the transaction + * @param txid the transaction's hash * * @return false if any key images to be removed cannot be found, otherwise true */ - bool remove_transaction_keyimages(const transaction& tx); + bool remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &txid); /** * @brief check if any of a transaction's spent key images are present in a given set @@ -491,7 +492,7 @@ namespace cryptonote * * @return true if any key images present in the set, otherwise false */ - static bool have_key_images(const std::unordered_set<crypto::key_image>& kic, const transaction& tx); + static bool have_key_images(const std::unordered_set<crypto::key_image>& kic, const transaction_prefix& tx); /** * @brief append the key images from a transaction to the given set @@ -501,7 +502,7 @@ namespace cryptonote * * @return false if any append fails, otherwise true */ - static bool append_key_images(std::unordered_set<crypto::key_image>& kic, const transaction& tx); + static bool append_key_images(std::unordered_set<crypto::key_image>& kic, const transaction_prefix& tx); /** * @brief check if a transaction is a valid candidate for inclusion in a block @@ -509,11 +510,11 @@ namespace cryptonote * @param txd the transaction to check (and info about it) * @param txid the txid of the transaction to check * @param txblob the transaction blob to check - * @param tx the parsed transaction, if successful + * @param tx the parsed transaction prefix, if successful * * @return true if the transaction is good to go, otherwise false */ - bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction &tx) const; + bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction&tx) const; /** * @brief mark all transactions double spending the one passed diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index 117790455..f645836a4 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -26,6 +26,20 @@ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +set(blocksdat "") +if(PER_BLOCK_CHECKPOINT) + if(APPLE AND DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(APPLE AND NOT DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(LINUX_32) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + else() + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + endif() + set(blocksdat "blocksdat.o") +endif() + set(daemon_sources command_parser_executor.cpp command_server.cpp @@ -67,7 +81,9 @@ monero_private_headers(daemon monero_add_executable(daemon ${daemon_sources} ${daemon_headers} - ${daemon_private_headers}) + ${daemon_private_headers} + ${blocksdat} +) target_link_libraries(daemon PRIVATE rpc @@ -90,8 +106,7 @@ target_link_libraries(daemon ${CMAKE_THREAD_LIBS_INIT} ${ZMQ_LIB} ${GNU_READLINE_LIBRARY} - ${EXTRA_LIBRARIES} - ${Blocks}) + ${EXTRA_LIBRARIES}) set_property(TARGET daemon PROPERTY OUTPUT_NAME "monerod") diff --git a/src/daemon/core.h b/src/daemon/core.h index eda8894a6..475f418d6 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -28,7 +28,6 @@ #pragma once -#include "blocks/blocks.h" #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "misc_log_ex.h" @@ -86,12 +85,7 @@ public: //initialize core here MGINFO("Initializing core..."); std::string config_subdir = get_config_subdir(); -#if defined(PER_BLOCK_CHECKPOINT) - cryptonote::GetCheckpointsCallback get_checkpoints = blocks::GetCheckpointsData; -#else - cryptonote::GetCheckpointsCallback get_checkpoints = nullptr; -#endif - if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str(), nullptr, get_checkpoints)) + if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str())) { return false; } diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index ea24e32eb..49d6d49cf 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -136,7 +136,19 @@ bool t_daemon::run(bool interactive) { throw std::runtime_error{"Can't run stopped daemon"}; } - tools::signal_handler::install(std::bind(&daemonize::t_daemon::stop_p2p, this)); + + std::atomic<bool> stop(false), shutdown(false); + boost::thread stop_thread = boost::thread([&stop, &shutdown, this] { + while (!stop) + epee::misc_utils::sleep_no_w(100); + if (shutdown) + this->stop_p2p(); + }); + epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ + stop = true; + stop_thread.join(); + }); + tools::signal_handler::install([&stop, &shutdown](int){ stop = shutdown = true; }); try { diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 8077f29fb..7e61e3603 100644 --- a/src/daemonizer/windows_daemonizer.inl +++ b/src/daemonizer/windows_daemonizer.inl @@ -31,6 +31,7 @@ #include "common/util.h" #include "daemonizer/windows_service.h" #include "daemonizer/windows_service_runner.h" +#include "cryptonote_core/cryptonote_core.h" #include <shlobj.h> #include <boost/filesystem/operations.hpp> diff --git a/src/debug_utilities/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp index ab8839636..2281d0734 100644 --- a/src/debug_utilities/object_sizes.cpp +++ b/src/debug_utilities/object_sizes.cpp @@ -29,6 +29,7 @@ #include <map> #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/tx_extra.h" +#include "cryptonote_core/cryptonote_core.h" #include "cryptonote_core/blockchain.h" #include "p2p/p2p_protocol_defs.h" #include "net/connection_basic.hpp" diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 727134f75..8f446f42a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -58,6 +58,12 @@ endif() set(device_private_headers) +if(PER_BLOCK_CHECKPOINT) + set(Blocks "blocks") +else() + set(Blocks "") +endif() + monero_private_headers(device ${device_private_headers}) @@ -73,4 +79,5 @@ target_link_libraries(device ringct_basic ${OPENSSL_CRYPTO_LIBRARIES} PRIVATE + ${Blocks} ${EXTRA_LIBRARIES}) diff --git a/src/device/device.cpp b/src/device/device.cpp index 50041baef..d5e3031ff 100644 --- a/src/device/device.cpp +++ b/src/device/device.cpp @@ -41,13 +41,26 @@ namespace hw { /* SETUP */ /* ======================================================================= */ - static std::unique_ptr<device_registry> registry; + static device_registry *get_device_registry(bool clear = false){ + static device_registry *registry = new device_registry(); + if (clear) + { + delete registry; + registry = NULL; + } + return registry; + } + + static void clear_device_registry(){ + get_device_registry(true); + } device_registry::device_registry(){ hw::core::register_all(registry); #ifdef WITH_DEVICE_LEDGER hw::ledger::register_all(registry); #endif + atexit(clear_device_registry); } bool device_registry::register_device(const std::string & device_name, device * hw_device){ @@ -80,18 +93,12 @@ namespace hw { } device& get_device(const std::string & device_descriptor) { - if (!registry){ - registry.reset(new device_registry()); - } - + device_registry *registry = get_device_registry(); return registry->get_device(device_descriptor); } bool register_device(const std::string & device_name, device * hw_device){ - if (!registry){ - registry.reset(new device_registry()); - } - + device_registry *registry = get_device_registry(); return registry->register_device(device_name, hw_device); } diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp index 562aca8b8..666255cb3 100644 --- a/src/device/device_io_hid.cpp +++ b/src/device/device_io_hid.cpp @@ -13,6 +13,7 @@ // #if defined(HAVE_HIDAPI) +#include <boost/scope_exit.hpp> #include "log.hpp" #include "device_io_hid.hpp" @@ -69,11 +70,47 @@ namespace hw { void device_io_hid::connect(void *params) { hid_conn_params *p = (struct hid_conn_params*)params; - this->connect(p->vid, p->pid, p->interface_number, p->usage_page, p->interface_OR_page); + this->connect(p->vid, p->pid, p->interface_number, p->usage_page); } - void device_io_hid::connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ) { - hid_device_info *hwdev_info, *hwdev_info_list; + hid_device_info *device_io_hid::find_device(hid_device_info *devices_list, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page) { + bool select_any = !interface_number && !usage_page; + + MDEBUG( "Looking for " << + (select_any ? "any HID Device" : "HID Device with") << + (interface_number ? (" interface_number " + std::to_string(interface_number.value())) : "") << + ((interface_number && usage_page) ? " or" : "") << + (usage_page ? (" usage_page " + std::to_string(usage_page.value())) : "")); + + hid_device_info *result = nullptr; + for (; devices_list != nullptr; devices_list = devices_list->next) { + BOOST_SCOPE_EXIT(&devices_list, &result) { + MDEBUG( (result == devices_list ? "SELECTED" : "SKIPPED ") << + " HID Device" << + " path " << safe_hid_path(devices_list) << + " interface_number " << devices_list->interface_number << + " usage_page " << devices_list->usage_page); + } + BOOST_SCOPE_EXIT_END + + if (result != nullptr) { + continue; + } + + if (select_any) { + result = devices_list; + } else if (interface_number && devices_list->interface_number == interface_number.value()) { + result = devices_list; + } else if (usage_page && devices_list->usage_page == usage_page.value()) { + result = devices_list; + } + } + + return result; + } + + void device_io_hid::connect(unsigned int vid, unsigned int pid, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page) { + hid_device_info *hwdev_info_list; hid_device *hwdev; this->disconnect(); @@ -81,17 +118,8 @@ namespace hw { hwdev_info_list = hid_enumerate(vid, pid); ASSERT_X(hwdev_info_list, "Unable to enumerate device "+std::to_string(vid)+":"+std::to_string(vid)+ ": "+ safe_hid_error(this->usb_device)); hwdev = NULL; - hwdev_info = hwdev_info_list; - while (hwdev_info) { - if ((interface_OR_page && ((usage_page == 0xffa0) || (interface_number == 0))) || - ((usage_page == 0xffa0) && (interface_number == 0)) ) { - MDEBUG("HID Device found: " << safe_hid_path(hwdev_info)); - hwdev = hid_open_path(hwdev_info->path); - break; - } else { - MDEBUG("HID Device discard: " << safe_hid_path(hwdev_info) << "("+std::to_string(hwdev_info->usage_page) << "," << std::to_string(hwdev_info->interface_number) << ")"); - } - hwdev_info = hwdev_info->next; + if (hid_device_info *device = find_device(hwdev_info_list, interface_number, usage_page)) { + hwdev = hid_open_path(device->path); } hid_free_enumeration(hwdev_info_list); ASSERT_X(hwdev, "Unable to open device "+std::to_string(pid)+":"+std::to_string(vid)); diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp index 560208c77..bb0f0a814 100644 --- a/src/device/device_io_hid.hpp +++ b/src/device/device_io_hid.hpp @@ -29,6 +29,7 @@ #if defined(HAVE_HIDAPI) +#include <boost/optional/optional.hpp> #include <hidapi/hidapi.h> #include "device_io.hpp" @@ -52,9 +53,8 @@ namespace hw { struct hid_conn_params { unsigned int vid; unsigned int pid; - unsigned int interface_number; - unsigned int usage_page; - bool interface_OR_page ; + int interface_number; + unsigned short usage_page; }; @@ -82,17 +82,15 @@ namespace hw { unsigned int wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len); unsigned int unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len); + hid_device_info *find_device(hid_device_info *devices_list, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page); public: bool hid_verbose = false; - const unsigned int OR_SELECT = 1; - const unsigned int AND_SELECT = 2; - - const unsigned char DEFAULT_CHANNEL = 0x0001; - const unsigned char DEFAULT_TAG = 0x01; - const unsigned int DEFAULT_PACKET_SIZE = 64; - const unsigned int DEFAULT_TIMEOUT = 120000; + static const unsigned short DEFAULT_CHANNEL = 0x0001; + static const unsigned char DEFAULT_TAG = 0x01; + static const unsigned int DEFAULT_PACKET_SIZE = 64; + static const unsigned int DEFAULT_TIMEOUT = 120000; device_io_hid(unsigned short channel, unsigned char tag, unsigned int packet_zize, unsigned int timeout); device_io_hid(); @@ -100,7 +98,7 @@ namespace hw { void init(); void connect(void *params); - void connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ); + void connect(unsigned int vid, unsigned int pid, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page); bool connected() const; int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len); void disconnect(); diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 456eda739..d879ee95a 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -48,21 +48,12 @@ namespace hw { /* ===================================================================== */ /* === Debug ==== */ /* ===================================================================== */ - #ifdef WIN32 - static char *pcsc_stringify_error(LONG rv) { - static __thread char out[20]; - sprintf_s(out, sizeof(out), "0x%08lX", rv); - - return out; - } - #endif void set_apdu_verbose(bool verbose) { apdu_verbose = verbose; } #define TRACKD MTRACE("hw") - #define ASSERT_RV(rv) CHECK_AND_ASSERT_THROW_MES((rv)==SCARD_S_SUCCESS, "Fail SCard API : (" << (rv) << ") "<< pcsc_stringify_error(rv)<<" Device="<<this->id<<", hCard="<<hCard<<", hContext="<<hContext); #define ASSERT_SW(sw,ok,msk) CHECK_AND_ASSERT_THROW_MES(((sw)&(mask))==(ok), "Wrong Device Status : SW=" << std::hex << (sw) << " (EXPECT=" << std::hex << (ok) << ", MASK=" << std::hex << (mask) << ")") ; #define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ; #define ASSERT_X(exp,msg) CHECK_AND_ASSERT_THROW_MES(exp, msg); @@ -185,7 +176,7 @@ namespace hw { #define INS_GET_RESPONSE 0xc0 - device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 10000) { + device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 120000) { this->id = device_id++; this->reset_buffer(); this->mode = NONE; @@ -349,7 +340,7 @@ namespace hw { bool device_ledger::connect(void) { this->disconnect(); - hw_device.connect(0x2c97,0x0001, 0, 0xffa0, hw_device.OR_SELECT); + hw_device.connect(0x2c97, 0x0001, 0, 0xffa0); this->reset(); #ifdef DEBUG_HWDEVICE cryptonote::account_public_address pubkey; diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index c9ca63f43..e9d2061e8 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -29,6 +29,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "common/command_line.h" +#include "cryptonote_core/cryptonote_core.h" #include "net_node.h" namespace nodetool diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 74924e4f4..9390626a8 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -937,7 +937,7 @@ namespace nodetool bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, - con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + con); if(!res) { @@ -1002,7 +1002,7 @@ namespace nodetool bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, - con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + con); if (!res) { bool is_priority = is_priority_node(na); @@ -1617,7 +1617,7 @@ namespace nodetool return false; } return true; - }, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + }); if(!r) { LOG_WARNING_CC(context, "Failed to call connect_async, network error."); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index be511a2d2..55ee66a79 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -924,6 +924,8 @@ namespace cryptonote return r; m_core.get_pool_transactions_and_spent_keys_info(res.transactions, res.spent_key_images, !request_has_rpc_origin || !m_restricted); + for (tx_info& txi : res.transactions) + txi.tx_blob = epee::string_tools::buff_to_hex_nodelimer(txi.tx_blob); res.status = CORE_RPC_STATUS_OK; return true; } @@ -1090,7 +1092,7 @@ namespace cryptonote { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to tx pub key in coinbase extra"); + LOG_ERROR("Failed to get tx pub key in coinbase extra"); return false; } res.reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key)); @@ -2118,6 +2120,8 @@ namespace cryptonote try { + // 0 is placeholder for the whole chain + const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); for (uint64_t amount: req.amounts) { static struct D @@ -2130,7 +2134,7 @@ namespace cryptonote } d; boost::unique_lock<boost::mutex> lock(d.mutex); - if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req.to_height) + if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req_to_height) { res.distributions.push_back({amount, d.cached_start_height, req.binary, d.cached_distribution, d.cached_base}); if (!req.cumulative) @@ -2145,23 +2149,23 @@ namespace cryptonote std::vector<uint64_t> distribution; uint64_t start_height, base; - if (!m_core.get_output_distribution(amount, req.from_height, req.to_height, start_height, distribution, base)) + if (!m_core.get_output_distribution(amount, req.from_height, req_to_height, start_height, distribution, base)) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Failed to get rct distribution"; return false; } - if (req.to_height > 0 && req.to_height >= req.from_height) + if (req_to_height > 0 && req_to_height >= req.from_height) { uint64_t offset = std::max(req.from_height, start_height); - if (offset <= req.to_height && req.to_height - offset + 1 < distribution.size()) - distribution.resize(req.to_height - offset + 1); + if (offset <= req_to_height && req_to_height - offset + 1 < distribution.size()) + distribution.resize(req_to_height - offset + 1); } if (amount == 0) { d.cached_from = req.from_height; - d.cached_to = req.to_height; + d.cached_to = req_to_height; d.cached_distribution = distribution; d.cached_start_height = start_height; d.cached_base = base; diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index 5fc382a1e..2050e88e2 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -318,7 +318,7 @@ namespace serialization { * \brief self explanatory */ template<class Stream> - bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>) + bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>, bool noeof) { return s.good(); } @@ -329,13 +329,13 @@ namespace serialization { * \detailed Also checks to make sure that the stream is not at EOF */ template<class Stream> - bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>) + bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>, bool noeof) { bool result = false; if (s.good()) { std::ios_base::iostate state = s.rdstate(); - result = EOF == s.peek(); + result = noeof || EOF == s.peek(); s.clear(state); } return result; @@ -347,9 +347,9 @@ namespace serialization { * \brief calls detail::do_check_stream_state for ar */ template<class Archive> - bool check_stream_state(Archive& ar) + bool check_stream_state(Archive& ar, bool noeof = false) { - return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving()); + return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving(), noeof); } /*! \fn serialize @@ -360,6 +360,17 @@ namespace serialization { inline bool serialize(Archive &ar, T &v) { bool r = do_serialize(ar, v); - return r && check_stream_state(ar); + return r && check_stream_state(ar, false); + } + + /*! \fn serialize + * + * \brief serializes \a v into \a ar + */ + template <class Archive, class T> + inline bool serialize_noeof(Archive &ar, T &v) + { + bool r = do_serialize(ar, v); + return r && check_stream_state(ar, true); } } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4ec7e3eb4..18b596662 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1640,7 +1640,7 @@ bool simple_wallet::blackball(const std::vector<std::string> &args) uint64_t amount = std::numeric_limits<uint64_t>::max(), offset, num_offsets; if (args.size() == 0) { - fail_msg_writer() << tr("usage: blackball <amount>/<offset> | <filename> [add]"); + fail_msg_writer() << tr("usage: mark_output_spent <amount>/<offset> | <filename> [add]"); return true; } @@ -1718,7 +1718,7 @@ bool simple_wallet::blackball(const std::vector<std::string> &args) } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to blackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to mark output spent: ") << e.what(); } return true; @@ -1729,7 +1729,7 @@ bool simple_wallet::unblackball(const std::vector<std::string> &args) std::pair<uint64_t, uint64_t> output; if (args.size() != 1) { - fail_msg_writer() << tr("usage: unblackball <amount>/<offset>"); + fail_msg_writer() << tr("usage: mark_output_unspent <amount>/<offset>"); return true; } @@ -1745,7 +1745,7 @@ bool simple_wallet::unblackball(const std::vector<std::string> &args) } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to mark output unspent: ") << e.what(); } return true; @@ -1756,7 +1756,7 @@ bool simple_wallet::blackballed(const std::vector<std::string> &args) std::pair<uint64_t, uint64_t> output; if (args.size() != 1) { - fail_msg_writer() << tr("usage: blackballed <amount>/<offset>"); + fail_msg_writer() << tr("usage: is_output_spent <amount>/<offset>"); return true; } @@ -1769,13 +1769,13 @@ bool simple_wallet::blackballed(const std::vector<std::string> &args) try { if (m_wallet->is_output_blackballed(output)) - message_writer() << tr("Blackballed: ") << output.first << "/" << output.second; + message_writer() << tr("Spent: ") << output.first << "/" << output.second; else - message_writer() << tr("not blackballed: ") << output.first << "/" << output.second; + message_writer() << tr("Not spent: ") << output.first << "/" << output.second; } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to check whether output is spent: ") << e.what(); } return true; @@ -2403,7 +2403,7 @@ simple_wallet::simple_wallet() "store-tx-info <1|0>\n " " Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference.\n " "default-ring-size <n>\n " - " Set the default ring size (default and minimum is 5).\n " + " Set the default ring size (obsolete).\n " "auto-refresh <1|0>\n " " Whether to automatically synchronize new blocks from the daemon.\n " "refresh-type <full|optimize-coinbase|no-coinbase|default>\n " @@ -2599,18 +2599,18 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::save_known_rings, this, _1), tr("save_known_rings"), tr("Save known rings to the shared rings database")); - m_cmd_binder.set_handler("blackball", + m_cmd_binder.set_handler("mark_output_spent", boost::bind(&simple_wallet::blackball, this, _1), - tr("blackball <amount>/<offset> | <filename> [add]"), - tr("Blackball output(s) so they never get selected as fake outputs in a ring")); - m_cmd_binder.set_handler("unblackball", + tr("mark_output_spent <amount>/<offset> | <filename> [add]"), + tr("Mark output(s) as spent so they never get selected as fake outputs in a ring")); + m_cmd_binder.set_handler("mark_output_unspent", boost::bind(&simple_wallet::unblackball, this, _1), - tr("unblackball <amount>/<offset>"), - tr("Unblackballs an output so it may get selected as a fake output in a ring")); - m_cmd_binder.set_handler("blackballed", + tr("mark_output_unspent <amount>/<offset>"), + tr("Marks an output as unspent so it may get selected as a fake output in a ring")); + m_cmd_binder.set_handler("is_output_spent", boost::bind(&simple_wallet::blackballed, this, _1), - tr("blackballed <amount>/<offset>"), - tr("Checks whether an output is blackballed")); + tr("is_output_spent <amount>/<offset>"), + tr("Checks whether an output is marked as spent")); m_cmd_binder.set_handler("version", boost::bind(&simple_wallet::version, this, _1), tr("version"), @@ -3032,7 +3032,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } crypto::secret_key viewkey; - if (viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) + if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) { fail_msg_writer() << tr("failed to parse view key secret key"); return false; diff --git a/src/version.cpp.in b/src/version.cpp.in index 55075a064..ff2405811 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_MONERO_VERSION_TAG "@VERSIONTAG@" -#define DEF_MONERO_VERSION "0.13.0.1-rc" +#define DEF_MONERO_VERSION "0.13.0.0-master" #define DEF_MONERO_RELEASE_NAME "Beryllium Bullet" #define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index de1bfdae1..1b4370c36 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -776,7 +776,7 @@ bool WalletImpl::setPassword(const std::string &password) { clearStatus(); try { - m_wallet->rewrite(m_wallet->get_wallet_file(), password); + m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password); m_password = password; } catch (const std::exception &e) { setStatusError(e.what()); @@ -2161,7 +2161,7 @@ bool WalletImpl::blackballOutputs(const std::vector<std::string> &outputs, bool bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add); if (!ret) { - setStatusError(tr("Failed to set blackballed outputs")); + setStatusError(tr("Failed to mark outputs as spent")); return false; } return true; @@ -2183,7 +2183,7 @@ bool WalletImpl::blackballOutput(const std::string &amount, const std::string &o bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset)); if (!ret) { - setStatusError(tr("Failed to blackball output")); + setStatusError(tr("Failed to mark output as spent")); return false; } return true; @@ -2205,7 +2205,7 @@ bool WalletImpl::unblackballOutput(const std::string &amount, const std::string bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset)); if (!ret) { - setStatusError(tr("Failed to unblackball output")); + setStatusError(tr("Failed to mark output as unspent")); return false; } return true; diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp index e5995e7fb..f562d6c06 100644 --- a/src/wallet/ringdb.cpp +++ b/src/wallet/ringdb.cpp @@ -412,13 +412,13 @@ bool ringdb::blackball_worker(const std::vector<std::pair<uint64_t, uint64_t>> & switch (op) { case BLACKBALL_BLACKBALL: - MDEBUG("Blackballing output " << output.first << "/" << output.second); + MDEBUG("Marking output " << output.first << "/" << output.second << " as spent"); dbr = mdb_cursor_put(cursor, &key, &data, MDB_APPENDDUP); if (dbr == MDB_KEYEXIST) dbr = 0; break; case BLACKBALL_UNBLACKBALL: - MDEBUG("Unblackballing output " << output.first << "/" << output.second); + MDEBUG("Marking output " << output.first << "/" << output.second << " as unspent"); dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH); if (dbr == 0) dbr = mdb_cursor_del(cursor, 0); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 7871fe99c..6b3a8533e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -37,6 +37,8 @@ #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/range/adaptor/transformed.hpp> #include "include_base_utils.h" using namespace epee; @@ -3611,6 +3613,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const std::stri if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject()) crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); + device_type = hw::device::device_type::SOFTWARE; // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { @@ -5563,10 +5566,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin rct::RangeProofType range_proof_type = rct::RangeProofBorromean; if (sd.use_bulletproofs) { - range_proof_type = rct::RangeProofBulletproof; - for (const rct::Bulletproof &proof: ptx.tx.rct_signatures.p.bulletproofs) - if (proof.V.size() > 1) - range_proof_type = rct::RangeProofPaddedBulletproof; + range_proof_type = rct::RangeProofPaddedBulletproof; } crypto::secret_key tx_key; std::vector<crypto::secret_key> additional_tx_keys; @@ -6968,6 +6968,8 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> LOG_PRINT_L1("Selecting real output: " << td.m_global_output_index << " for " << print_money(amount)); } + std::unordered_map<const char*, std::set<uint64_t>> picks; + // while we still need more mixins uint64_t num_usable_outs = num_outs; bool allow_blackballed = false; @@ -6982,7 +6984,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> // outputs, we still need to reach the minimum ring size) if (allow_blackballed) break; - MINFO("Not enough non blackballed outputs, we'll allow blackballed ones"); + MINFO("Not enough output not marked as spent, we'll allow outputs marked as spent"); allow_blackballed = true; num_usable_outs = num_outs; } @@ -7066,11 +7068,15 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> } seen_indices.emplace(i); - LOG_PRINT_L2("picking " << i << " as " << type); + picks[type].insert(i); req.outputs.push_back({amount, i}); ++num_found; } + for (const auto &pick: picks) + MDEBUG("picking " << pick.first << " outputs: " << + boost::join(pick.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ")); + // if we had enough unusable outputs, we might fall off here and still // have too few outputs, so we stuff with one to keep counts good, and // we'll error out later @@ -7086,8 +7092,15 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> [](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; }); } - for (auto i: req.outputs) - LOG_PRINT_L1("asking for output " << i.index << " for " << print_money(i.amount)); + if (ELPP->vRegistry()->allowed(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY)) + { + std::map<uint64_t, std::set<uint64_t>> outs; + for (const auto &i: req.outputs) + outs[i.amount].insert(i.index); + for (const auto &o: outs) + MDEBUG("asking for outputs with amount " << print_money(o.first) << ": " << + boost::join(o.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ")); + } // get the keys for those m_daemon_rpc_mutex.lock(); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e0b631aaf..1b63d65b6 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -2822,8 +2822,7 @@ namespace tools { try { - m_wallet->rewrite(m_wallet->get_wallet_file(), req.new_password); - m_wallet->store(); + m_wallet->change_password(m_wallet->get_wallet_file(), req.old_password, req.new_password); LOG_PRINT_L0("Wallet password changed."); } catch (const std::exception& e) diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index ab896aa3b..35ea11902 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -35,6 +35,7 @@ #include <string> #include "common/util.h" #include "net/http_server_impl_base.h" +#include "math_helper.h" #include "wallet_rpc_server_commands_defs.h" #include "wallet2.h" |