diff options
Diffstat (limited to 'src')
38 files changed, 382 insertions, 431 deletions
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 88034a927..33c3341fa 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1333,10 +1333,11 @@ public: * @brief get a txpool transaction's metadata * * @param txid the transaction id of the transation to lookup + * @param meta the metadata to return * - * @return the metadata associated with that transaction + * @return true if the tx meta was found, false otherwise */ - virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const = 0; + virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const = 0; /** * @brief get a txpool transaction's blob diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 931bbec4b..d19399bec 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1621,7 +1621,7 @@ void BlockchainLMDB::remove_txpool_tx(const crypto::hash& txid) } } -txpool_tx_meta_t BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid) const +bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1632,12 +1632,14 @@ txpool_tx_meta_t BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid) co MDB_val k = {sizeof(txid), (void *)&txid}; MDB_val v; auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET); + if (result == MDB_NOTFOUND) + return false; if (result != 0) throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str())); - const txpool_tx_meta_t meta = *(const txpool_tx_meta_t*)v.mv_data; + meta = *(const txpool_tx_meta_t*)v.mv_data; TXN_POSTFIX_RDONLY(); - return meta; + return true; } bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 85b62b5db..ecd14f11b 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -246,7 +246,7 @@ public: virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const; virtual bool txpool_has_tx(const crypto::hash &txid) const; virtual void remove_txpool_tx(const crypto::hash& txid); - virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const; + virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const; virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const; virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const; virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, bool include_unrelayed_txes = true) const; diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index bd32e0c55..6c55e8d2d 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -29,9 +29,9 @@ set(blocksdat "") if(PER_BLOCK_CHECKPOINT) if(APPLE) - 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} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + 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.*) 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} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + 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() diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 758deb7e4..edb8881e0 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -594,8 +594,8 @@ int main(int argc, char* argv[]) const command_line::arg_descriptor<std::string> arg_database = { "database", available_dbs.c_str(), default_db_type }; - const command_line::arg_descriptor<bool> arg_verify = {"verify", - "Verify blocks and transactions during import", true}; + const command_line::arg_descriptor<bool> arg_verify = {"guard-against-pwnage", + "Verify blocks and transactions during import (only disable if you exported the file yourself)", true}; const command_line::arg_descriptor<bool> arg_batch = {"batch", "Batch transactions for faster import", true}; const command_line::arg_descriptor<bool> arg_resume = {"resume", diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index 3a866af5b..9317d585b 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -30,8 +30,8 @@ if(APPLE) add_library(blocks STATIC blockexports.c) set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) else() - add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -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} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + 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_library(blocks STATIC blocks.o testnet_blocks.o blockexports.c) set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) endif() diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 7ad08ea83..7ce0229da 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -35,7 +35,6 @@ set(common_sources download.cpp util.cpp i18n.cpp - memwipe.c password.cpp perf_timer.cpp threadpool.cpp @@ -64,7 +63,6 @@ set(common_private_headers util.h varint.h i18n.h - memwipe.h password.h perf_timer.h stack_trace.h @@ -76,7 +74,8 @@ monero_private_headers(common monero_add_library(common ${common_sources} ${common_headers} - ${common_private_headers}) + ${common_private_headers} + DEPENDS generate_translations_header) target_link_libraries(common PUBLIC epee @@ -92,9 +91,5 @@ target_link_libraries(common ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) -if(HAVE_C11) -SET_PROPERTY(SOURCE memwipe.c PROPERTY COMPILE_FLAGS -std=c11) -endif() - #monero_install_headers(common # ${common_headers}) diff --git a/src/common/memwipe.c b/src/common/memwipe.c deleted file mode 100644 index da7e9f346..000000000 --- a/src/common/memwipe.c +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2017, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file Copyright (c) 2009-2015 The Bitcoin Core developers - -#define __STDC_WANT_LIB_EXT1__ 1 -#include <string.h> -#include <stdlib.h> -#ifdef HAVE_EXPLICIT_BZERO -#include <strings.h> -#endif -#include "memwipe.h" - -#if defined(_MSC_VER) -#define SCARECROW \ - __asm; -#else -#define SCARECROW \ - __asm__ __volatile__("" : : "r"(ptr) : "memory"); -#endif - -#ifdef HAVE_MEMSET_S - -void *memwipe(void *ptr, size_t n) -{ - if (memset_s(ptr, n, 0, n)) - { - abort(); - } - SCARECROW // might as well... - return ptr; -} - -#elif defined HAVE_EXPLICIT_BZERO - -void *memwipe(void *ptr, size_t n) -{ - explicit_bzero(ptr, n); - SCARECROW - return ptr; -} - -#else - -/* The memory_cleanse implementation is taken from Bitcoin */ - -/* Compilers have a bad habit of removing "superfluous" memset calls that - * are trying to zero memory. For example, when memset()ing a buffer and - * then free()ing it, the compiler might decide that the memset is - * unobservable and thus can be removed. - * - * Previously we used OpenSSL which tried to stop this by a) implementing - * memset in assembly on x86 and b) putting the function in its own file - * for other platforms. - * - * This change removes those tricks in favour of using asm directives to - * scare the compiler away. As best as our compiler folks can tell, this is - * sufficient and will continue to be so. - * - * Adam Langley <agl@google.com> - * Commit: ad1907fe73334d6c696c8539646c21b11178f20f - * BoringSSL (LICENSE: ISC) - */ -static void memory_cleanse(void *ptr, size_t len) -{ - memset(ptr, 0, len); - - /* As best as we can tell, this is sufficient to break any optimisations that - might try to eliminate "superfluous" memsets. If there's an easy way to - detect memset_s, it would be better to use that. */ - SCARECROW -} - -void *memwipe(void *ptr, size_t n) -{ - memory_cleanse(ptr, n); - SCARECROW - return ptr; -} - -#endif diff --git a/src/common/password.cpp b/src/common/password.cpp index dc0856160..011123300 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -46,7 +46,7 @@ #include "readline_buffer.h" #endif -#include "common/memwipe.h" +#include "memwipe.h" namespace { diff --git a/src/common/util.cpp b/src/common/util.cpp index 2a2f50c4f..a4a435104 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -39,6 +39,7 @@ #include "wipeable_string.h" using namespace epee; +#include "crypto/crypto.h" #include "util.h" #include "memwipe.h" #include "cryptonote_config.h" diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index fd71a87e7..764b30273 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -76,6 +76,7 @@ monero_add_library(cncrypto ${crypto_private_headers}) target_link_libraries(cncrypto PUBLIC + epee ${Boost_SYSTEM_LIBRARY} PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/crypto/blake256.c b/src/crypto/blake256.c index 1e43f9c4d..95b2a6927 100644 --- a/src/crypto/blake256.c +++ b/src/crypto/blake256.c @@ -157,7 +157,7 @@ void blake256_update(state *S, const uint8_t *data, uint64_t datalen) { int left = S->buflen >> 3; int fill = 64 - left; - if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) { + if (left && (((datalen >> 3)) >= (unsigned) fill)) { memcpy((void *) (S->buf + left), (void *) data, fill); S->t[0] += 512; if (S->t[0] == 0) S->t[1]++; diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h index a9665030d..c11e4aa2f 100644 --- a/src/crypto/chacha.h +++ b/src/crypto/chacha.h @@ -39,7 +39,7 @@ #if defined(__cplusplus) #include <memory.h> -#include "common/memwipe.h" +#include "memwipe.h" #include "hash.h" namespace crypto { diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 0ce5e6d7a..a929302c1 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -41,7 +41,7 @@ #include "common/pod-class.h" #include "common/util.h" -#include "common/memwipe.h" +#include "memwipe.h" #include "generic-ops.h" #include "hex.h" #include "span.h" diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 821c21d84..c81901f4e 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -36,7 +36,6 @@ #include <cstring> // memcmp #include <sstream> #include <atomic> -#include "serialization/serialization.h" #include "serialization/variant.h" #include "serialization/vector.h" #include "serialization/binary_archive.h" diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 1183fda06..929be0d5a 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -34,7 +34,7 @@ using namespace epee; #include "cryptonote_basic_impl.h" #include "string_tools.h" #include "serialization/binary_utils.h" -#include "serialization/vector.h" +#include "serialization/container.h" #include "cryptonote_format_utils.h" #include "cryptonote_config.h" #include "misc_language.h" diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 21fa63842..5f6dc3bd6 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -35,6 +35,7 @@ using namespace epee; #include <boost/algorithm/string.hpp> #include "wipeable_string.h" #include "string_tools.h" +#include "serialization/string.h" #include "cryptonote_format_utils.h" #include "cryptonote_config.h" #include "crypto/crypto.h" diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 709c5e852..4af987c3b 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4198,9 +4198,9 @@ uint64_t Blockchain::get_txpool_tx_count(bool include_unrelayed_txes) const return m_db->get_txpool_tx_count(include_unrelayed_txes); } -txpool_tx_meta_t Blockchain::get_txpool_tx_meta(const crypto::hash& txid) const +bool Blockchain::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { - return m_db->get_txpool_tx_meta(txid); + return m_db->get_txpool_tx_meta(txid, meta); } bool Blockchain::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 2d5307ac0..25e573a2c 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -914,7 +914,7 @@ namespace cryptonote void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta); void remove_txpool_tx(const crypto::hash &txid); uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const; - txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const; + bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const; bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const; cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const; bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = true) const; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index e6f217463..8773c1f74 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -371,7 +371,12 @@ namespace cryptonote try { LockedTXN lock(m_blockchain); - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(id); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(id, meta)) + { + MERROR("Failed to find tx in txpool"); + return false; + } cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(id); if (!parse_and_validate_tx_from_blob(txblob, tx)) { @@ -514,10 +519,13 @@ namespace cryptonote { try { - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(it->first); - meta.relayed = true; - meta.last_relayed_time = now; - m_blockchain.update_txpool_tx(it->first, meta); + txpool_tx_meta_t meta; + if (m_blockchain.get_txpool_tx_meta(it->first, meta)) + { + meta.relayed = true; + meta.last_relayed_time = now; + m_blockchain.update_txpool_tx(it->first, meta); + } } catch (const std::exception &e) { @@ -696,7 +704,11 @@ namespace cryptonote { try { - meta = m_blockchain.get_txpool_tx_meta(tx_id_hash); + if (!m_blockchain.get_txpool_tx_meta(tx_id_hash, meta)) + { + MERROR("Failed to get tx meta from txpool"); + return false; + } if (!meta.relayed) // Do not include that transaction if in restricted mode and it's not relayed continue; @@ -918,7 +930,13 @@ namespace cryptonote { for (const crypto::hash &txid: it->second) { - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(txid); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(txid, meta)) + { + MERROR("Failed to find tx meta in txpool"); + // continue, not fatal + continue; + } if (!meta.double_spend_seen) { MDEBUG("Marking " << txid << " as double spending " << itk.k_image); @@ -998,7 +1016,12 @@ namespace cryptonote auto sorted_it = m_txs_by_fee_and_receive_time.begin(); while (sorted_it != m_txs_by_fee_and_receive_time.end()) { - txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(sorted_it->second); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta)) + { + MERROR(" failed to find tx meta"); + continue; + } LOG_PRINT_L2("Considering " << sorted_it->second << ", size " << meta.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase)); // Can not exceed maximum block size diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 8aef31a5a..5d25d1058 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1059,6 +1059,11 @@ skip: num_txs += block_entry.txs.size(); std::vector<tx_verification_context> tvc; m_core.handle_incoming_txs(block_entry.txs, tvc, true, true, false); + if (tvc.size() != block_entry.txs.size()) + { + LOG_ERROR_CCONTEXT("Internal error: tvc.size() != block_entry.txs.size()"); + return true; + } std::list<blobdata>::const_iterator it = block_entry.txs.begin(); for (size_t i = 0; i < tvc.size(); ++i, ++it) { diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index ad84db450..49d3bc836 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -29,9 +29,9 @@ set(blocksdat "") if(PER_BLOCK_CHECKPOINT) if(APPLE) - 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} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + 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.*) 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} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + 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() diff --git a/src/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt index 5ce2198ae..79964e873 100644 --- a/src/mnemonics/CMakeLists.txt +++ b/src/mnemonics/CMakeLists.txt @@ -57,6 +57,7 @@ monero_add_library(mnemonics ${mnemonics_private_headers}) target_link_libraries(mnemonics PUBLIC + epee easylogging ${Boost_SYSTEM_LIBRARY} PRIVATE diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index ba67952aa..f44ad40aa 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -410,7 +410,7 @@ namespace crypto std::vector<std::string> words_store; uint32_t word_list_length = word_list.size(); - // 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 + // 4 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 for (unsigned int i=0; i < len/4; i++, words += ' ') { uint32_t w1, w2, w3; diff --git a/src/p2p/CMakeLists.txt b/src/p2p/CMakeLists.txt index 123b0a272..3fc053dc7 100644 --- a/src/p2p/CMakeLists.txt +++ b/src/p2p/CMakeLists.txt @@ -46,5 +46,6 @@ target_link_libraries(p2p ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} + ${Boost_SERIALIZATION_LIBRARY} PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 5ea2dcc7c..2df797360 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -47,7 +47,7 @@ extern "C" { #include "hex.h" #include "span.h" -#include "serialization/serialization.h" +#include "serialization/vector.h" #include "serialization/debug_archive.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 748c6b8c1..19ea93902 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -101,6 +101,7 @@ target_link_libraries(rpc_base epee ${Boost_REGEX_LIBRARY} ${Boost_THREAD_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} PRIVATE ${EXTRA_LIBRARIES}) @@ -125,6 +126,7 @@ target_link_libraries(daemon_messages target_link_libraries(daemon_rpc_server LINK_PRIVATE + rpc cryptonote_core cryptonote_protocol daemon_messages diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a6109cb89..4966b107d 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -106,8 +106,9 @@ namespace cryptonote if (rpc_config->login) http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password()); + auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); }; return epee::http_server_impl_base<core_rpc_server, connection_context>::init( - std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) + rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) ); } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/serialization/container.h b/src/serialization/container.h new file mode 100644 index 000000000..978a59d2a --- /dev/null +++ b/src/serialization/container.h @@ -0,0 +1,113 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "serialization.h" + +namespace serialization +{ + namespace detail + { + template <typename Archive, class T> + bool serialize_container_element(Archive& ar, T& e) + { + return ::do_serialize(ar, e); + } + + template <typename Archive> + bool serialize_container_element(Archive& ar, uint32_t& e) + { + ar.serialize_varint(e); + return true; + } + + template <typename Archive> + bool serialize_container_element(Archive& ar, uint64_t& e) + { + ar.serialize_varint(e); + return true; + } + + template <typename C> + void do_reserve(C &c, size_t N) {} + } +} + +template <template <bool> class Archive, typename C> +bool do_serialize_container(Archive<false> &ar, C &v) +{ + size_t cnt; + ar.begin_array(cnt); + if (!ar.stream().good()) + return false; + v.clear(); + + // very basic sanity check + if (ar.remaining_bytes() < cnt) { + ar.stream().setstate(std::ios::failbit); + return false; + } + + ::serialization::detail::do_reserve(v, cnt); + + for (size_t i = 0; i < cnt; i++) { + if (i > 0) + ar.delimit_array(); + typename C::value_type e; + if (!::serialization::detail::serialize_container_element(ar, e)) + return false; + ::serialization::detail::do_add(v, std::move(e)); + if (!ar.stream().good()) + return false; + } + ar.end_array(); + return true; +} + +template <template <bool> class Archive, typename C> +bool do_serialize_container(Archive<true> &ar, C &v) +{ + size_t cnt = v.size(); + ar.begin_array(cnt); + for (auto i = v.begin(); i != v.end(); ++i) + { + if (!ar.stream().good()) + return false; + if (i != v.begin()) + ar.delimit_array(); + if(!::serialization::detail::serialize_container_element(ar, const_cast<typename C::value_type&>(*i))) + return false; + if (!ar.stream().good()) + return false; + } + ar.end_array(); + return true; +} diff --git a/src/common/memwipe.h b/src/serialization/deque.h index c3b4ce8ab..994d3f195 100644 --- a/src/common/memwipe.h +++ b/src/serialization/deque.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -30,55 +30,35 @@ #pragma once -#ifdef __cplusplus -#include <array> +#include <deque> -extern "C" { -#endif +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::deque<T> &v); +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::deque<T> &v); -void *memwipe(void *src, size_t n); - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -namespace tools { - - /// Scrubs data in the contained type upon destruction. - /// - /// Primarily useful for making sure that private keys don't stick around in - /// memory after the objects that held them have gone out of scope. - template <class T> - struct scrubbed : public T { - using type = T; - - ~scrubbed() { - scrub(); +namespace serialization +{ + namespace detail + { + template <typename T> + void do_reserve(std::deque<T> &c, size_t N) + { + c.reserve(N); } - /// Destroy the contents of the contained type. - void scrub() { - static_assert(std::is_pod<T>::value, - "T cannot be auto-scrubbed. T must be POD."); - static_assert(std::is_trivially_destructible<T>::value, - "T cannot be auto-scrubbed. T must be trivially destructable."); - memwipe(this, sizeof(T)); + template <typename T> + void do_add(std::deque<T> &c, T &&e) + { + c.emplace_back(std::move(e)); } - }; + } +} - template <class T, size_t N> - using scrubbed_arr = scrubbed<std::array<T, N>>; -} // namespace tools +#include "serialization.h" -// Partial specialization for std::is_pod<tools::scrubbed<T>> so that it can -// pretend to be the containted type in those contexts. -namespace std -{ - template<class t_scrubbee> - struct is_pod<tools::scrubbed<t_scrubbee>> { - static const bool value = is_pod<t_scrubbee>::value; - }; -} +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); } -#endif // __cplusplus diff --git a/src/serialization/list.h b/src/serialization/list.h index d0fb72163..d725458e7 100644 --- a/src/serialization/list.h +++ b/src/serialization/list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2015, The Monero Project +// Copyright (c) 2014-2017, The Monero Project // // All rights reserved. // @@ -30,71 +30,29 @@ #pragma once -#include "serialization.h" +#include <list> + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::list<T> &v); +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::list<T> &v); namespace serialization { namespace detail { - template <typename Archive, class T> - bool serialize_list_element(Archive& ar, T& e) - { - return ::do_serialize(ar, e); - } - - template <typename Archive> - bool serialize_list_element(Archive& ar, uint64_t& e) + template <typename T> + void do_add(std::list<T> &c, T &&e) { - ar.serialize_varint(e); - return true; + c.emplace_back(std::move(e)); } } } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::list<T> &l) -{ - size_t cnt; - ar.begin_array(cnt); - if (!ar.stream().good()) - return false; - l.clear(); - - // very basic sanity check - if (ar.remaining_bytes() < cnt) { - ar.stream().setstate(std::ios::failbit); - return false; - } - - for (size_t i = 0; i < cnt; i++) { - if (i > 0) - ar.delimit_array(); - l.push_back(T()); - T &t = l.back(); - if (!::serialization::detail::serialize_list_element(ar, t)) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} +#include "serialization.h" template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::list<T> &l) -{ - size_t cnt = l.size(); - ar.begin_array(cnt); - for (typename std::list<T>::iterator i = l.begin(); i != l.end(); ++i) { - if (!ar.stream().good()) - return false; - if (i != l.begin()) - ar.delimit_array(); - if(!::serialization::detail::serialize_list_element(ar, *i)) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} +bool do_serialize(Archive<false> &ar, std::list<T> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::list<T> &v) { return do_serialize_container(ar, v); } + diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index 9e23f0791..56496c790 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -63,15 +63,17 @@ struct is_blob_type { typedef boost::false_type type; }; template <class T> struct has_free_serializer { typedef boost::true_type type; }; -/*! \struct is_pair_type +/*! \struct is_basic_type * * \brief a descriptor for dispatching serialize */ template <class T> -struct is_pair_type { typedef boost::false_type type; }; +struct is_basic_type { typedef boost::false_type type; }; template<typename F, typename S> -struct is_pair_type<std::pair<F,S>> { typedef boost::true_type type; }; +struct is_basic_type<std::pair<F,S>> { typedef boost::true_type type; }; +template<> +struct is_basic_type<std::string> { typedef boost::true_type type; }; /*! \struct serializer * @@ -89,7 +91,7 @@ struct is_pair_type<std::pair<F,S>> { typedef boost::true_type type; }; template <class Archive, class T> struct serializer{ static bool serialize(Archive &ar, T &v) { - return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_pair_type<T>::type()); + return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_basic_type<T>::type()); } template<typename A> static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type, A a) { @@ -361,9 +363,3 @@ namespace serialization { return r && check_stream_state(ar); } } - -#include "string.h" -#include "vector.h" -#include "list.h" -#include "pair.h" -#include "set.h" diff --git a/src/serialization/set.h b/src/serialization/set.h index 54b4eb3ab..e6eff62a9 100644 --- a/src/serialization/set.h +++ b/src/serialization/set.h @@ -30,98 +30,29 @@ #pragma once -#include "serialization.h" +#include <set> template <template <bool> class Archive, class T> bool do_serialize(Archive<false> &ar, std::set<T> &v); template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::set<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v); namespace serialization { namespace detail { - template <typename Archive, class T> - bool serialize_set_element(Archive& ar, T& e) + template <typename T> + void do_add(std::set<T> &c, T &&e) { - return ::do_serialize(ar, e); - } - - template <typename Archive> - bool serialize_set_element(Archive& ar, uint32_t& e) - { - ar.serialize_varint(e); - return true; - } - - template <typename Archive> - bool serialize_set_element(Archive& ar, uint64_t& e) - { - ar.serialize_varint(e); - return true; + c.insert(std::move(e)); } } } -template <template <bool> class Archive, class T> -bool do_serialize_set(Archive<false> &ar, T &v) -{ - size_t cnt; - ar.begin_array(cnt); - if (!ar.stream().good()) - return false; - v.clear(); - - // very basic sanity check - if (ar.remaining_bytes() < cnt) { - ar.stream().setstate(std::ios::failbit); - return false; - } - - for (size_t i = 0; i < cnt; i++) { - if (i > 0) - ar.delimit_array(); - typename T::key_type k; - if (!::serialization::detail::serialize_set_element(ar, k)) - return false; - v.insert(std::move(k)); - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} - -template <template <bool> class Archive, class T> -bool do_serialize_set(Archive<true> &ar, T &v) -{ - size_t cnt = v.size(); - ar.begin_array(cnt); - bool first = true; - for (const typename T::key_type &k: v) { - if (!ar.stream().good()) - return false; - if (!first) - ar.delimit_array(); - if(!::serialization::detail::serialize_set_element(ar, const_cast<typename T::key_type&>(k))) - return false; - if (!ar.stream().good()) - return false; - first = false; - } - ar.end_array(); - return true; -} +#include "serialization.h" template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_set(ar, v); } +bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_container(ar, v); } template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_set(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); } +bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_container(ar, v); } + diff --git a/src/serialization/unordered_set.h b/src/serialization/unordered_set.h new file mode 100644 index 000000000..b277f0c4a --- /dev/null +++ b/src/serialization/unordered_set.h @@ -0,0 +1,58 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include <set> + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v); +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v); + +namespace serialization +{ + namespace detail + { + template <typename T> + void do_add(std::unordered_set<T> &c, T &&e) + { + c.insert(std::move(e)); + } + } +} + +#include "serialization.h" + +template <template <bool> class Archive, class T> +bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, class T> +bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); } + diff --git a/src/serialization/vector.h b/src/serialization/vector.h index 12fd59558..9cf3d8272 100644 --- a/src/serialization/vector.h +++ b/src/serialization/vector.h @@ -30,6 +30,7 @@ #pragma once +#include <vector> #include "serialization.h" template <template <bool> class Archive, class T> @@ -37,91 +38,28 @@ bool do_serialize(Archive<false> &ar, std::vector<T> &v); template <template <bool> class Archive, class T> bool do_serialize(Archive<true> &ar, std::vector<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::deque<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::deque<T> &v); - namespace serialization { namespace detail { - template <typename Archive, class T> - bool serialize_vector_element(Archive& ar, T& e) - { - return ::do_serialize(ar, e); - } - - template <typename Archive> - bool serialize_vector_element(Archive& ar, uint32_t& e) + template <typename T> + void do_reserve(std::vector<T> &c, size_t N) { - ar.serialize_varint(e); - return true; + c.reserve(N); } - template <typename Archive> - bool serialize_vector_element(Archive& ar, uint64_t& e) + template <typename T> + void do_add(std::vector<T> &c, T &&e) { - ar.serialize_varint(e); - return true; + c.emplace_back(std::move(e)); } } } -template <template <bool> class Archive, class T> -bool do_serialize_vd(Archive<false> &ar, T &v) -{ - size_t cnt; - ar.begin_array(cnt); - if (!ar.stream().good()) - return false; - v.clear(); - - // very basic sanity check - if (ar.remaining_bytes() < cnt) { - ar.stream().setstate(std::ios::failbit); - return false; - } - - v.reserve(cnt); - for (size_t i = 0; i < cnt; i++) { - if (i > 0) - ar.delimit_array(); - v.resize(i+1); - if (!::serialization::detail::serialize_vector_element(ar, v[i])) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} - -template <template <bool> class Archive, class T> -bool do_serialize_vd(Archive<true> &ar, T &v) -{ - size_t cnt = v.size(); - ar.begin_array(cnt); - for (size_t i = 0; i < cnt; i++) { - if (!ar.stream().good()) - return false; - if (i > 0) - ar.delimit_array(); - if(!::serialization::detail::serialize_vector_element(ar, v[i])) - return false; - if (!ar.stream().good()) - return false; - } - ar.end_array(); - return true; -} +#include "container.h" template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_vd(ar, v); } +bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); } template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_vd(ar, v); } +bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_vd(ar, v); } -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_vd(ar, v); } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f4f24ed77..b9a3e45b4 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3307,6 +3307,13 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args { if (!parse_subaddress_indices(local_args[0], subaddr_indices)) return true; + local_args.erase(local_args.begin()); + } + + if (local_args.size() > 0) + { + fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=<N>]"); + return true; } tools::wallet2::transfer_container transfers; @@ -4528,6 +4535,12 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector<std::string> &args_) { + if(m_wallet->testnet()) + { + fail_msg_writer() << tr("donations are not enabled on the testnet"); + return true; + } + std::vector<std::string> local_args = args_; if(local_args.empty() || local_args.size() > 5) { @@ -6195,6 +6208,7 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &args) try { + LOCK_IDLE_SCOPE(); if (!m_wallet->export_key_images(filename)) { fail_msg_writer() << tr("failed to save file ") << filename; @@ -6227,6 +6241,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args) } std::string filename = args[0]; + LOCK_IDLE_SCOPE(); try { uint64_t spent = 0, unspent = 0; @@ -6258,6 +6273,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args) if (m_wallet->ask_password() && !get_and_verify_password()) { return true; } std::string filename = args[0]; + LOCK_IDLE_SCOPE(); try { std::vector<tools::wallet2::transfer_details> outs = m_wallet->export_outputs(); @@ -6356,6 +6372,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args) boost::archive::binary_iarchive ar(iss); ar >> outputs; } + LOCK_IDLE_SCOPE(); size_t n_outputs = m_wallet->import_outputs(outputs); success_msg_writer() << boost::lexical_cast<std::string>(n_outputs) << " outputs imported"; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c4f8f3457..2af41f588 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -53,6 +53,7 @@ using namespace epee; #include "profile_tools.h" #include "crypto/crypto.h" #include "serialization/binary_utils.h" +#include "serialization/string.h" #include "cryptonote_basic/blobdatatype.h" #include "mnemonics/electrum-words.h" #include "common/i18n.h" @@ -62,7 +63,7 @@ using namespace epee; #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include "common/json_util.h" -#include "common/memwipe.h" +#include "memwipe.h" #include "common/base58.h" #include "ringct/rctSigs.h" @@ -2035,6 +2036,11 @@ void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, pull_hashes(0, blocks_start_height, short_chain_history, hashes); if (hashes.size() <= 3) return; + if (blocks_start_height < m_blockchain.offset()) + { + MERROR("Blocks start before blockchain offset: " << blocks_start_height << " " << m_blockchain.offset()); + return; + } if (hashes.size() + current_index < stop_height) { drop_from_short_history(short_chain_history, 3); std::list<crypto::hash>::iterator right = hashes.end(); @@ -5833,7 +5839,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry if (m_multisig) { crypto::public_key ignore = m_multisig_threshold == m_multisig_signers.size() ? crypto::null_pkey : multisig_signers.front(); - multisig_sigs.push_back({tx.rct_signatures, ignore, used_L, {}, msout}); + multisig_sigs.push_back({tx.rct_signatures, ignore, used_L, std::unordered_set<crypto::public_key>(), msout}); if (m_multisig_threshold < m_multisig_signers.size()) { @@ -5860,7 +5866,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_prefix_hash(ms_tx) != prefix_hash, error::wallet_internal_error, "Multisig txes do not share prefix"); - multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, {}, msout}); + multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, std::unordered_set<crypto::public_key>(), msout}); ms_tx.rct_signatures = tx.rct_signatures; THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_hash(ms_tx) != cryptonote::get_transaction_hash(tx), error::wallet_internal_error, "Multisig txes differ by more than the signatures"); @@ -6159,7 +6165,8 @@ void wallet2::light_wallet_get_unspent_outs() add_tx_pub_key_to_extra(td.m_tx, tx_pub_key); td.m_key_image = unspent_key_image; - td.m_key_image_known = !m_watch_only; + td.m_key_image_known = !m_watch_only && !m_multisig; + td.m_key_image_partial = m_multisig; td.m_amount = o.amount; td.m_pk_index = 0; td.m_internal_output_index = o.index; @@ -6833,6 +6840,17 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp const size_t estimated_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof); needed_fee = calculate_fee(fee_per_kb, estimated_tx_size, fee_multiplier); + uint64_t inputs = 0, outputs = needed_fee; + for (size_t idx: tx.selected_transfers) inputs += m_transfers[idx].amount(); + for (const auto &o: tx.dsts) outputs += o.amount; + + if (inputs < outputs) + { + LOG_PRINT_L2("We don't have enough for the basic fee, switching to adding_fee"); + adding_fee = true; + goto skip_tx; + } + LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " << tx.selected_transfers.size() << " inputs"); if (use_rct) @@ -6908,6 +6926,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp } } +skip_tx: // if unused_*_indices is empty while unused_*_indices_per_subaddr has multiple elements, and if we still have something to pay, // pop front of unused_*_indices_per_subaddr and have unused_*_indices point to the front of unused_*_indices_per_subaddr if ((!dsts.empty() && dsts[0].amount > 0) || adding_fee) @@ -6960,37 +6979,48 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet"); - std::map<uint32_t, uint64_t> balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account); - - if (subaddr_indices.empty()) - { - // in case subaddress index wasn't specified, choose non-empty subaddress randomly (with index=0 being chosen last) - if (balance_per_subaddr.count(0) == 1 && balance_per_subaddr.size() > 1) - balance_per_subaddr.erase(0); - auto i = balance_per_subaddr.begin(); - std::advance(i, crypto::rand<size_t>() % balance_per_subaddr.size()); - subaddr_indices.insert(i->first); - } - for (uint32_t i : subaddr_indices) - LOG_PRINT_L2("Spending from subaddress index " << i); + std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr; - // gather all dust and non-dust outputs of specified subaddress + // gather all dust and non-dust outputs of specified subaddress (if any) and below specified threshold (if any) + bool fund_found = false; for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; - if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) + if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && (subaddr_indices.empty() || subaddr_indices.count(td.m_subaddr_index.minor) == 1)) { + fund_found = true; if (below == 0 || td.amount() < below) { if ((td.is_rct()) || is_valid_decomposed_amount(td.amount())) - unused_transfers_indices.push_back(i); + unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].first.push_back(i); else - unused_dust_indices.push_back(i); + unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].second.push_back(i); } } } + THROW_WALLET_EXCEPTION_IF(!fund_found, error::wallet_internal_error, "No unlocked balance in the specified subaddress(es)"); + THROW_WALLET_EXCEPTION_IF(unused_transfer_dust_indices_per_subaddr.empty(), error::wallet_internal_error, "The smallest amount found is not below the specified threshold"); - THROW_WALLET_EXCEPTION_IF(unused_transfers_indices.empty() && unused_dust_indices.empty(), error::not_enough_money, 0, 0, 0); // not sure if a new error class (something like 'cant_sweep_empty'?) should be introduced + if (subaddr_indices.empty()) + { + // in case subaddress index wasn't specified, choose non-empty subaddress randomly (with index=0 being chosen last) + if (unused_transfer_dust_indices_per_subaddr.count(0) == 1 && unused_transfer_dust_indices_per_subaddr.size() > 1) + unused_transfer_dust_indices_per_subaddr.erase(0); + auto i = unused_transfer_dust_indices_per_subaddr.begin(); + std::advance(i, crypto::rand<size_t>() % unused_transfer_dust_indices_per_subaddr.size()); + unused_transfers_indices = i->second.first; + unused_dust_indices = i->second.second; + LOG_PRINT_L2("Spending from subaddress index " << i->first); + } + else + { + for (const auto& p : unused_transfer_dust_indices_per_subaddr) + { + unused_transfers_indices.insert(unused_transfers_indices.end(), p.second.first.begin(), p.second.first.end()); + unused_dust_indices.insert(unused_dust_indices.end(), p.second.second.begin(), p.second.second.end()); + LOG_PRINT_L2("Spending from subaddress index " << p.first); + } + } return create_transactions_from(address, is_subaddress, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra, trusted_daemon); } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 3aba76da0..fc2c43c04 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -89,6 +89,8 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ wallet_rpc_server::~wallet_rpc_server() { + if (m_wallet) + delete m_wallet; } //------------------------------------------------------------------------------------------------------------------------------ void wallet_rpc_server::set_wallet(wallet2 *cr) @@ -229,8 +231,9 @@ namespace tools m_http_client.set_server(walvars->get_daemon_address(), walvars->get_daemon_login()); m_net_server.set_threads_prefix("RPC"); + auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); }; return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init( - std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) + rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) ); } //------------------------------------------------------------------------------------------------------------------------------ |