diff options
57 files changed, 1303 insertions, 565 deletions
diff --git a/.travis.yml b/.travis.yml index ba2215905..4d49e3539 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ env: # ARM v8 - HOST=aarch64-linux-gnu PACKAGES="python3 gperf g++-aarch64-linux-gnu" # i686 Win - - HOST=i686-w64-mingw32 DEP_OPTS="NO_QT=1" PACKAGES="python3 g++-mingw-w64-i686 qttools5-dev-tools" + - HOST=i686-w64-mingw32 DEP_OPTS="NO_QT=1" PACKAGES="python3 g++-mingw-w64-i686 qttools5-dev-tools" MAKEJOBS=-j2 # i686 Linux - HOST=i686-pc-linux-gnu PACKAGES="gperf cmake g++-multilib python3-zmq" # Win64 @@ -22,6 +22,7 @@ Portions Copyright (c) 2012-2013 The Cryptonote developers. - [Dependencies](#dependencies) - [Internationalization](#Internationalization) - [Using Tor](#using-tor) + - [Pruning](#Pruning) - [Debugging](#Debugging) - [Known issues](#known-issues) @@ -551,6 +552,10 @@ The produced binaries still link libc dynamically. If the binary is compiled on Packages are available for +* Debian Buster + + See the [instructions in the whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get) + * Debian Bullseye and Sid ```bash @@ -558,9 +563,9 @@ Packages are available for ``` More info and versions in the [Debian package tracker](https://tracker.debian.org/pkg/monero). -* Arch Linux (via [AUR](https://aur.archlinux.org/)): - - Stable release: [`monero`](https://aur.archlinux.org/packages/monero) - - Bleeding edge: [`monero-git`](https://aur.archlinux.org/packages/monero-git) + +* Arch Linux (via Community packages): + [`monero`](https://www.archlinux.org/packages/community/x86_64/monero/) * Void Linux: @@ -574,6 +579,21 @@ More info and versions in the [Debian package tracker](https://tracker.debian.or guix package -i monero ``` +* Gentoo [Monero overlay](https://github.com/gentoo-monero/gentoo-monero) + + ```bash + emerge --noreplace eselect-repository + eselect repository enable monero + emaint sync -r monero + echo '*/*::monero ~amd64' >> /etc/portage/package.accept_keywords + emerge net-p2p/monero + ``` + +* macOS (homebrew) + ```bash + brew install monero + ``` + * Docker ```bash @@ -679,6 +699,16 @@ DNS_PUBLIC=tcp torsocks ./monerod --p2p-bind-ip 127.0.0.1 --no-igd --rpc-bind-ip --data-dir /home/amnesia/Persistent/your/directory/to/the/blockchain ``` +## Pruning + +As of May 2020, the full Monero blockchain file is about 80 GB. One can store a pruned blockchain, which is about 28 GB. +A pruned blockchain can only serve part of the historical chain data to other peers, but is otherwise identical in +functionality to the full blockchain. +To use a pruned blockchain, it is best to start the initial sync with --prune-blockchain. However, it is also possible +to prune an existing blockchain using the monero-blockchain-prune tool or using the --prune-blockchain monerod option +with an existing chain. If an existing chain exists, pruning will temporarily require disk space to store both the full +and pruned blockchains. + ## Debugging This section contains general instructions for debugging failed installs or problems encountered with Monero. First, ensure you are running the latest version built from the Github repo. diff --git a/external/qrcodegen/CMakeLists.txt b/external/qrcodegen/CMakeLists.txt index a9060e3e8..094b49760 100644 --- a/external/qrcodegen/CMakeLists.txt +++ b/external/qrcodegen/CMakeLists.txt @@ -1,7 +1,8 @@ project(libqrcodegen) add_library(qrcodegen STATIC QrCode.cpp) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +set_target_properties(qrcodegen PROPERTIES POSITION_INDEPENDENT_CODE ON) +set_target_properties(qrcodegen PROPERTIES CXX_STANDARD 11) target_include_directories(qrcodegen PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 5c8dece2a..a9a7d035f 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -179,7 +179,7 @@ void BlockchainDB::pop_block() pop_block(blk, txs); } -void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr) +void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr) { const transaction &tx = txp.first; @@ -281,12 +281,13 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck time1 = epee::misc_utils::get_tick_count(); uint64_t num_rct_outs = 0; - add_transaction(blk_hash, std::make_pair(blk.miner_tx, tx_to_blob(blk.miner_tx))); + blobdata miner_bd = tx_to_blob(blk.miner_tx); + add_transaction(blk_hash, std::make_pair(blk.miner_tx, blobdata_ref(miner_bd))); if (blk.miner_tx.version == 2) num_rct_outs += blk.miner_tx.vout.size(); int tx_i = 0; crypto::hash tx_hash = crypto::null_hash; - for (const std::pair<transaction, blobdata>& tx : txs) + for (const std::pair<transaction, blobdata_ref>& tx : txs) { tx_hash = blk.tx_hashes[tx_i]; add_transaction(blk_hash, tx, &tx_hash); diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 9a321437b..abebb52b4 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -440,7 +440,7 @@ private: * @param tx_prunable_hash the hash of the prunable part of the transaction * @return the transaction ID */ - virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) = 0; + virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) = 0; /** * @brief remove data about a transaction @@ -568,7 +568,7 @@ protected: * @param tx_hash_ptr the hash of the transaction, if already calculated * @param tx_prunable_hash_ptr the hash of the prunable part of the transaction, if already calculated */ - void add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL); + void add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL); mutable uint64_t time_tx_exists = 0; //!< a performance metric uint64_t time_commit1 = 0; //!< a performance metric @@ -1524,7 +1524,7 @@ public: * * @param details the details of the transaction to add */ - virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& details) = 0; + virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const txpool_tx_meta_t& details) = 0; /** * @brief update a txpool transaction's metadata @@ -1644,7 +1644,7 @@ public: * @param: data: the metadata for the block * @param: blob: the block's blob */ - virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob) = 0; + virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob) = 0; /** * @brief get an alternative block by hash @@ -1687,7 +1687,7 @@ public: * * @return false if the function returns false for any transaction, otherwise true */ - virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const = 0; + virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const = 0; /** * @brief runs a function over all key images stored @@ -1779,7 +1779,7 @@ public: * * @return false if the function returns false for any output, otherwise true */ - virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *blob)> f, bool include_blob = false) const = 0; + virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata_ref *blob)> f, bool include_blob = false) const = 0; // diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 6ea55d09d..8aa958825 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -856,7 +856,7 @@ void BlockchainLMDB::remove_block() throw1(DB_ERROR(lmdb_error("Failed to add removal of block info to db transaction: ", result).c_str())); } -uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& txp, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) +uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& txp, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -896,7 +896,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons if (result) throw0(DB_ERROR(lmdb_error("Failed to add tx data to db transaction: ", result).c_str())); - const cryptonote::blobdata &blob = txp.second; + const cryptonote::blobdata_ref &blob = txp.second; MDB_val_sized(blobval, blob); unsigned int unprunable_size = tx.unprunable_size; @@ -1756,7 +1756,7 @@ void BlockchainLMDB::unlock() auto_txn.commit(); \ } while(0) -void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta) +void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const txpool_tx_meta_t &meta) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -2308,7 +2308,7 @@ bool BlockchainLMDB::check_pruning() return prune_worker(prune_mode_check, 0); } -bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, relay_category category) const +bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)> f, bool include_blob, relay_category category) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -2334,8 +2334,7 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data; if (!meta.matches(category)) continue; - const cryptonote::blobdata *passed_bd = NULL; - cryptonote::blobdata bd; + cryptonote::blobdata_ref bd; if (include_blob) { MDB_val b; @@ -2344,11 +2343,10 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, throw0(DB_ERROR("Failed to find txpool tx blob to match metadata")); if (result) throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx blob: ", result).c_str())); - bd.assign(reinterpret_cast<const char*>(b.mv_data), b.mv_size); - passed_bd = &bd; + bd = {reinterpret_cast<const char*>(b.mv_data), b.mv_size}; } - if (!f(txid, meta, passed_bd)) { + if (!f(txid, meta, &bd)) { ret = false; break; } @@ -2359,7 +2357,7 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, return ret; } -bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&, const alt_block_data_t&, const cryptonote::blobdata*)> f, bool include_blob) const +bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&, const alt_block_data_t&, const cryptonote::blobdata_ref*)> f, bool include_blob) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -2384,15 +2382,13 @@ bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&, if (v.mv_size < sizeof(alt_block_data_t)) throw0(DB_ERROR("alt_blocks record is too small")); const alt_block_data_t *data = (const alt_block_data_t*)v.mv_data; - const cryptonote::blobdata *passed_bd = NULL; - cryptonote::blobdata bd; + cryptonote::blobdata_ref bd; if (include_blob) { - bd.assign(reinterpret_cast<const char*>(v.mv_data) + sizeof(alt_block_data_t), v.mv_size - sizeof(alt_block_data_t)); - passed_bd = &bd; + bd = {reinterpret_cast<const char*>(v.mv_data) + sizeof(alt_block_data_t), v.mv_size - sizeof(alt_block_data_t)}; } - if (!f(blkid, *data, passed_bd)) { + if (!f(blkid, *data, &bd)) { ret = false; break; } @@ -3604,8 +3600,7 @@ bool BlockchainLMDB::for_blocks_range(const uint64_t& h1, const uint64_t& h2, st if (ret) throw0(DB_ERROR("Failed to enumerate blocks")); uint64_t height = *(const uint64_t*)k.mv_data; - blobdata bd; - bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size); + blobdata_ref bd{reinterpret_cast<char*>(v.mv_data), v.mv_size}; block b; if (!parse_and_validate_block_from_blob(bd, b)) throw0(DB_ERROR("Failed to parse block from blob retrieved from the db")); @@ -3660,15 +3655,16 @@ bool BlockchainLMDB::for_all_transactions(std::function<bool(const crypto::hash& if (ret) throw0(DB_ERROR(lmdb_error("Failed to enumerate transactions: ", ret).c_str())); transaction tx; - blobdata bd; - bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size); if (pruned) { + blobdata_ref bd{reinterpret_cast<char*>(v.mv_data), v.mv_size}; if (!parse_and_validate_tx_base_from_blob(bd, tx)) throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db")); } else { + blobdata bd; + bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size); ret = mdb_cursor_get(m_cur_txs_prunable, &k, &v, MDB_SET); if (ret) throw0(DB_ERROR(lmdb_error("Failed to get prunable tx data the db: ", ret).c_str())); @@ -4402,7 +4398,7 @@ uint8_t BlockchainLMDB::get_hard_fork_version(uint64_t height) const return ret; } -void BlockchainLMDB::add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob) +void BlockchainLMDB::add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -4969,7 +4965,7 @@ void BlockchainLMDB::migrate_0_1() } MDB_dbi o_txs; - blobdata bd; + blobdata_ref bd; block b; MDB_val hk; @@ -5051,7 +5047,7 @@ void BlockchainLMDB::migrate_0_1() } else if (result) throw0(DB_ERROR(lmdb_error("Failed to get a record from blocks: ", result).c_str())); - bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size); + bd = {reinterpret_cast<char*>(v.mv_data), v.mv_size}; if (!parse_and_validate_block_from_blob(bd, b)) throw0(DB_ERROR("Failed to parse block from blob retrieved from the db")); @@ -5062,7 +5058,7 @@ void BlockchainLMDB::migrate_0_1() result = mdb_cursor_get(c_txs, &hk, &v, MDB_SET); if (result) throw0(DB_ERROR(lmdb_error("Failed to get record from txs: ", result).c_str())); - bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size); + bd = {reinterpret_cast<char*>(v.mv_data), v.mv_size}; if (!parse_and_validate_tx_from_blob(bd, tx)) throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db")); add_transaction(null_hash, std::make_pair(std::move(tx), bd), &b.tx_hashes[j]); @@ -5184,8 +5180,7 @@ void BlockchainLMDB::migrate_1_2() else if (result) throw0(DB_ERROR(lmdb_error("Failed to get a record from txs: ", result).c_str())); - cryptonote::blobdata bd; - bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size); + cryptonote::blobdata bd{reinterpret_cast<char*>(v.mv_data), v.mv_size}; transaction tx; if (!parse_and_validate_tx_from_blob(bd, tx)) throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db")); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 5abb8014f..568882ae5 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -283,7 +283,7 @@ public: virtual bool has_key_image(const crypto::key_image& img) const; - virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& meta); + virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const txpool_tx_meta_t& meta); virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& meta); virtual uint64_t get_txpool_tx_count(relay_category category = relay_category::broadcasted) const; virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const; @@ -296,20 +296,20 @@ public: virtual bool update_pruning(); virtual bool check_pruning(); - virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob); + virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob); virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *blob); virtual void remove_alt_block(const crypto::hash &blkid); virtual uint64_t get_alt_block_count(); virtual void drop_alt_blocks(); - 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, relay_category category = relay_category::broadcasted) const; + virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)> f, bool include_blob = false, relay_category category = relay_category::broadcasted) const; virtual bool for_all_key_images(std::function<bool(const crypto::key_image&)>) const; virtual bool for_blocks_range(const uint64_t& h1, const uint64_t& h2, std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const; virtual bool for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)>, bool pruned) const; virtual bool for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const; virtual bool for_all_outputs(uint64_t amount, const std::function<bool(uint64_t height)> &f) const; - virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *blob)> f, bool include_blob = false) const; + virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata_ref *blob)> f, bool include_blob = false) const; virtual uint64_t add_block( const std::pair<block, blobdata>& blk , size_t block_weight @@ -376,7 +376,7 @@ private: virtual void remove_block(); - virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash); + virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash); virtual void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx); diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h index 92911d081..9e74b33f1 100644 --- a/src/blockchain_db/testdb.h +++ b/src/blockchain_db/testdb.h @@ -111,7 +111,7 @@ public: virtual std::vector<std::vector<uint64_t>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector<std::vector<uint64_t>>(); } virtual bool has_key_image(const crypto::key_image& img) const override { return false; } virtual void remove_block() override { } - virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;} + virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;} virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) override {} virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return 0;} virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) override {} @@ -127,7 +127,7 @@ public: virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const override { return std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>(); } virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector<uint64_t> &distribution, uint64_t &base) const override { return false; } - virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const cryptonote::txpool_tx_meta_t& details) override {} + virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const cryptonote::txpool_tx_meta_t& details) override {} virtual void update_txpool_tx(const crypto::hash &txid, const cryptonote::txpool_tx_meta_t& details) override {} virtual uint64_t get_txpool_tx_count(relay_category tx_relay = relay_category::broadcasted) const override { return 0; } virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const override { return false; } @@ -136,7 +136,7 @@ public: virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const override { return false; } virtual uint64_t get_database_size() const override { return 0; } virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const override { return ""; } - virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; } + virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; } virtual void add_block( const cryptonote::block& blk , size_t block_weight @@ -160,12 +160,12 @@ public: virtual uint64_t get_max_block_size() override { return 100000000; } virtual void add_max_block_size(uint64_t sz) override { } - virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob) override {} + virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob) override {} virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *blob) override { return false; } virtual void remove_alt_block(const crypto::hash &blkid) override {} virtual uint64_t get_alt_block_count() override { return 0; } virtual void drop_alt_blocks() override {} - virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *blob)> f, bool include_blob = false) const override { return true; } + virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata_ref *blob)> f, bool include_blob = false) const override { return true; } }; } diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index a847f6a9d..a8197483f 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -28,8 +28,6 @@ #include <boost/range/adaptor/transformed.hpp> #include <boost/algorithm/string.hpp> -#include <boost/archive/portable_binary_iarchive.hpp> -#include <boost/archive/portable_binary_oarchive.hpp> #include "common/unordered_containers_boost_serialization.h" #include "common/command_line.h" #include "common/varint.h" diff --git a/src/cryptonote_basic/blobdatatype.h b/src/cryptonote_basic/blobdatatype.h index 6906e0c9d..7f899993b 100644 --- a/src/cryptonote_basic/blobdatatype.h +++ b/src/cryptonote_basic/blobdatatype.h @@ -31,10 +31,11 @@ #pragma once #include <string> +#include <boost/utility/string_ref_fwd.hpp> #include "span.h" namespace cryptonote { typedef std::string blobdata; - typedef epee::span<const char> blobdata_ref; + typedef boost::string_ref blobdata_ref; } diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index bc6a378f2..c70ae1df1 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -37,7 +37,7 @@ #include <sstream> #include <atomic> #include "serialization/variant.h" -#include "serialization/vector.h" +#include "serialization/containers.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" #include "serialization/debug_archive.h" diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 541393fa9..2600854a9 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -34,7 +34,6 @@ using namespace epee; #include "cryptonote_basic_impl.h" #include "string_tools.h" #include "serialization/binary_utils.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_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 6f89cc7ae..b3d39a616 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -36,7 +36,6 @@ #include <boost/serialization/set.hpp> #include <boost/serialization/map.hpp> #include <boost/serialization/is_bitwise_serializable.hpp> -#include <boost/archive/binary_iarchive.hpp> #include <boost/archive/portable_binary_iarchive.hpp> #include <boost/archive/portable_binary_oarchive.hpp> #include "cryptonote_basic.h" diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 3fd059ac1..d808a9c1d 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -209,7 +209,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx) + bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx) { std::stringstream ss; ss << tx_blob; @@ -222,7 +222,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx) + bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx) { std::stringstream ss; ss << tx_blob; @@ -234,7 +234,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx) + bool parse_and_validate_tx_prefix_from_blob(const blobdata_ref& tx_blob, transaction_prefix& tx) { std::stringstream ss; ss << tx_blob; @@ -244,7 +244,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash) + bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash) { std::stringstream ss; ss << tx_blob; @@ -258,7 +258,7 @@ namespace cryptonote return get_transaction_hash(tx, tx_hash); } //--------------------------------------------------------------- - 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_ref& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash) { if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash)) return false; @@ -958,7 +958,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - void get_blob_hash(const epee::span<const char>& blob, crypto::hash& res) + void get_blob_hash(const blobdata_ref& blob, crypto::hash& res) { cn_fast_hash(blob.data(), blob.size(), res); } @@ -1045,7 +1045,7 @@ namespace cryptonote return h; } //--------------------------------------------------------------- - crypto::hash get_blob_hash(const epee::span<const char>& blob) + crypto::hash get_blob_hash(const blobdata_ref& blob) { crypto::hash h = null_hash; get_blob_hash(blob, h); @@ -1065,7 +1065,7 @@ namespace cryptonote return get_transaction_hash(t, res, NULL); } //--------------------------------------------------------------- - bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res) + bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blob, crypto::hash& res) { if (t.version == 1) return false; @@ -1073,7 +1073,7 @@ namespace cryptonote if (blob && unprunable_size) { CHECK_AND_ASSERT_MES(unprunable_size <= blob->size(), false, "Inconsistent transaction unprunable and blob sizes"); - cryptonote::get_blob_hash(epee::span<const char>(blob->data() + unprunable_size, blob->size() - unprunable_size), res); + cryptonote::get_blob_hash(blobdata_ref(blob->data() + unprunable_size, blob->size() - unprunable_size), res); } else { @@ -1090,7 +1090,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blobdata) + crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blobdata) { crypto::hash res; if (t.is_prunable_hash_valid()) @@ -1168,7 +1168,7 @@ namespace cryptonote // base rct CHECK_AND_ASSERT_MES(prefix_size <= unprunable_size && unprunable_size <= blob.size(), false, "Inconsistent transaction prefix, unprunable and blob sizes"); - cryptonote::get_blob_hash(epee::span<const char>(blob.data() + prefix_size, unprunable_size - prefix_size), hashes[1]); + cryptonote::get_blob_hash(blobdata_ref(blob.data() + prefix_size, unprunable_size - prefix_size), hashes[1]); // prunable rct if (t.rct_signatures.type == rct::RCTTypeNull) @@ -1177,7 +1177,8 @@ namespace cryptonote } else { - CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, &blob, hashes[2]), false, "Failed to get tx prunable hash"); + cryptonote::blobdata_ref blobref(blob); + CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, &blobref, hashes[2]), false, "Failed to get tx prunable hash"); } // the tx hash is the hash of the 3 hashes @@ -1241,13 +1242,15 @@ namespace cryptonote return blob; } //--------------------------------------------------------------- - bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob) + bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob) { blobdata bd; + blobdata_ref bdref; if (!blob) { bd = block_to_blob(b); - blob = &bd; + bdref = bd; + blob = &bdref; } bool hash_result = get_object_hash(get_block_hashing_blob(b), res); @@ -1330,7 +1333,7 @@ namespace cryptonote return res; } //--------------------------------------------------------------- - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash) + bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash) { std::stringstream ss; ss << b_blob; @@ -1348,12 +1351,12 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b) + bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b) { return parse_and_validate_block_from_blob(b_blob, b, NULL); } //--------------------------------------------------------------- - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash) + bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash) { return parse_and_validate_block_from_blob(b_blob, b, &block_hash); } diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 5639e38d0..636a88b9a 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -52,11 +52,11 @@ namespace cryptonote crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx, hw::device &hwdev); 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, crypto::hash& tx_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); + bool parse_and_validate_tx_prefix_from_blob(const blobdata_ref& tx_blob, transaction_prefix& tx); + bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); + bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash); + bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx); + bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx); bool is_v1_tx(const blobdata_ref& tx_blob); bool is_v1_tx(const blobdata& tx_blob); @@ -102,27 +102,27 @@ namespace cryptonote bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev); void get_blob_hash(const blobdata& blob, crypto::hash& res); - void get_blob_hash(const epee::span<const char>& blob, crypto::hash& res); + void get_blob_hash(const blobdata_ref& blob, crypto::hash& res); crypto::hash get_blob_hash(const blobdata& blob); - crypto::hash get_blob_hash(const epee::span<const char>& blob); + crypto::hash get_blob_hash(const blobdata_ref& blob); std::string short_hash_str(const crypto::hash& h); crypto::hash get_transaction_hash(const transaction& t); bool get_transaction_hash(const transaction& t, crypto::hash& res); bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size); bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size); - bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res); - crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob = NULL); + bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blob, crypto::hash& res); + crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blob = NULL); bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size); crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash); blobdata get_block_hashing_blob(const block& b); - bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob = NULL); + bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob = NULL); bool get_block_hash(const block& b, crypto::hash& res); crypto::hash get_block_hash(const block& b); - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash); - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b); - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash); + bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash); + bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b); + bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash); bool get_inputs_money_amount(const transaction& tx, uint64_t& money); uint64_t get_outs_money_amount(const transaction& tx); bool check_inputs_types_supported(const transaction& tx); diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index 3cbc4e5a4..b23253d4a 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -91,17 +91,16 @@ namespace cryptonote uint64_t get_block_reward() const { return m_block_reward; } static constexpr uint8_t BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE = 90; - static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 50; + static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 0; static constexpr uint8_t BACKGROUND_MINING_MAX_IDLE_THRESHOLD_PERCENTAGE = 99; static constexpr uint16_t BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS = 10; static constexpr uint16_t BACKGROUND_MINING_MIN_MIN_IDLE_INTERVAL_IN_SECONDS = 10; static constexpr uint16_t BACKGROUND_MINING_MAX_MIN_IDLE_INTERVAL_IN_SECONDS = 3600; static constexpr uint8_t BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE = 40; - static constexpr uint8_t BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE = 5; - static constexpr uint8_t BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE = 50; + static constexpr uint8_t BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE = 1; + static constexpr uint8_t BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE = 100; static constexpr uint8_t BACKGROUND_MINING_MINER_MONITOR_INVERVAL_IN_SECONDS = 10; static constexpr uint64_t BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS = 400; // ramp up - static constexpr uint64_t BACKGROUND_MINING_MIN_MINER_EXTRA_SLEEP_MILLIS = 5; private: bool worker_thread(); diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 8c4e61d4d..8051ee9fa 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -178,6 +178,7 @@ #define HF_VERSION_REJECT_SIGS_IN_COINBASE 12 #define HF_VERSION_ENFORCE_MIN_AGE 12 #define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 12 +#define HF_VERSION_EXACT_COINBASE 13 #define PER_KB_FEE_QUANTIZATION_DECIMALS 8 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 882ee4894..20dc7f9fb 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1397,8 +1397,8 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl MERROR_VER("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << "), cumulative_block_weight " << cumulative_block_weight); return false; } - // From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust - if (version < 2) + // From hard fork 2 till 12, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust + if (version < 2 || version >= HF_VERSION_EXACT_COINBASE) { if(base_reward + fee != money_in_use) { @@ -2158,7 +2158,7 @@ bool Blockchain::get_alternative_blocks(std::vector<block>& blocks) const CRITICAL_REGION_LOCAL(m_blockchain_lock); blocks.reserve(m_db->get_alt_block_count()); - m_db->for_all_alt_blocks([&blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata *blob) { + m_db->for_all_alt_blocks([&blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref *blob) { if (!blob) { MERROR("No blob, but blobs were requested"); @@ -5121,7 +5121,7 @@ cryptonote::blobdata Blockchain::get_txpool_tx_blob(const crypto::hash& txid, re return m_db->get_txpool_tx_blob(txid, tx_category); } -bool Blockchain::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, relay_category tx_category) const +bool Blockchain::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)> f, bool include_blob, relay_category tx_category) const { return m_db->for_all_txpool_txes(f, include_blob, tx_category); } @@ -5192,7 +5192,7 @@ std::vector<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>> blocks_ext_by_hash alt_blocks; alt_blocks.reserve(m_db->get_alt_block_count()); - m_db->for_all_alt_blocks([&alt_blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata *blob) { + m_db->for_all_alt_blocks([&alt_blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref *blob) { if (!blob) { MERROR("No blob, but blobs were requested"); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 703dd6400..85aa5d4e2 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -31,6 +31,9 @@ #pragma once #include <boost/asio/io_service.hpp> #include <boost/function/function_fwd.hpp> +#if BOOST_VERSION >= 107400 +#include <boost/serialization/library_version_type.hpp> +#endif #include <boost/serialization/serialization.hpp> #include <boost/serialization/version.hpp> #include <boost/serialization/list.hpp> @@ -985,7 +988,7 @@ namespace cryptonote 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, relay_category tx_category) const; cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const; - bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category tx_category = relay_category::broadcasted) const; + bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category tx_category = relay_category::broadcasted) const; bool txpool_tx_matches_category(const crypto::hash& tx_hash, relay_category category); bool is_within_compiled_block_hash_area() const { return is_within_compiled_block_hash_area(m_db->height()); } diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 7cb0e4062..85bcf2246 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -622,7 +622,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); - m_blockchain.for_all_txpool_txes([this, &hashes, &txes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) { + m_blockchain.for_all_txpool_txes([this, &hashes, &txes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) { const auto tx_relay_method = meta.get_relay_method(); if (tx_relay_method != relay_method::block && tx_relay_method != relay_method::fluff) return true; @@ -670,7 +670,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); 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*) { + m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) { uint64_t tx_age = time(nullptr) - meta.receive_time; if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !meta.kept_by_block) || @@ -737,7 +737,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain.get_db()); txs.reserve(m_blockchain.get_txpool_tx_count()); - m_blockchain.for_all_txpool_txes([this, now, &txs, &change_timestamps](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *){ + m_blockchain.for_all_txpool_txes([this, now, &txs, &change_timestamps](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *){ // 0 fee transactions are never relayed if(!meta.pruned && meta.fee > 0 && !meta.do_not_relay) { @@ -844,7 +844,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted; txs.reserve(m_blockchain.get_txpool_tx_count(include_sensitive)); - m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ + m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){ transaction tx; if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(*bd, tx) : parse_and_validate_tx_from_blob(*bd, tx))) { @@ -864,7 +864,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted; txs.reserve(m_blockchain.get_txpool_tx_count(include_sensitive)); - m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ + m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){ txs.push_back(txid); return true; }, false, category); @@ -877,7 +877,7 @@ namespace cryptonote const uint64_t now = time(NULL); const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted; backlog.reserve(m_blockchain.get_txpool_tx_count(include_sensitive)); - m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ + m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){ backlog.push_back({meta.weight, meta.fee, meta.receive_time - now}); return true; }, false, category); @@ -893,7 +893,7 @@ namespace cryptonote stats.txs_total = m_blockchain.get_txpool_tx_count(include_sensitive); std::vector<uint32_t> weights; weights.reserve(stats.txs_total); - m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ + m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){ weights.push_back(meta.weight); stats.bytes_total += meta.weight; if (!stats.bytes_min || meta.weight < stats.bytes_min) @@ -978,10 +978,10 @@ namespace cryptonote const size_t count = m_blockchain.get_txpool_tx_count(include_sensitive_data); tx_infos.reserve(count); key_image_infos.reserve(count); - m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ + m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){ tx_info txi; txi.id_hash = epee::string_tools::pod_to_hex(txid); - txi.tx_blob = *bd; + txi.tx_blob = blobdata(bd->data(), bd->size()); transaction tx; if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(*bd, tx) : parse_and_validate_tx_from_blob(*bd, tx))) { @@ -1035,7 +1035,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); tx_infos.reserve(m_blockchain.get_txpool_tx_count()); key_image_infos.reserve(m_blockchain.get_txpool_tx_count()); - m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ + m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){ cryptonote::rpc::tx_in_pool txi; txi.tx_hash = txid; if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(*bd, txi.tx) : parse_and_validate_tx_from_blob(*bd, txi.tx))) @@ -1331,7 +1331,7 @@ namespace cryptonote std::stringstream ss; CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); - m_blockchain.for_all_txpool_txes([&ss, short_format](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *txblob) { + m_blockchain.for_all_txpool_txes([&ss, short_format](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *txblob) { ss << "id: " << txid << std::endl; if (!short_format) { cryptonote::transaction tx; @@ -1509,7 +1509,7 @@ namespace cryptonote std::unordered_set<crypto::hash> remove; m_txpool_weight = 0; - m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) { + m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) { m_txpool_weight += meta.weight; if (meta.weight > tx_weight_limit) { LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.weight << " bytes), removing it from pool"); @@ -1581,7 +1581,7 @@ namespace cryptonote for (int pass = 0; pass < 2; ++pass) { const bool kept = pass == 1; - 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) { + bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd) { if (!!kept != !!meta.kept_by_block) return true; cryptonote::transaction_prefix tx; diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index af7f1b89d..337885509 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1937,8 +1937,8 @@ skip: if (local_stripe == 0) return false; // don't request pre-bulletprooof pruned blocks, we can't reconstruct their weight (yet) - static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8); - if (first_block_height + nblocks - 1 < bp_fork_height) + static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(HF_VERSION_SMALLER_BP); + if (first_block_height < bp_fork_height) return false; // assumes the span size is less or equal to the stripe size bool full_data_needed = tools::get_pruning_stripe(first_block_height, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES) == local_stripe diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index bbc165cfa..b439dc47e 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -39,6 +39,7 @@ #include "misc_language.h" #include "string_tools.h" #include "time_helper.h" +#include "serialization/serialization.h" #include "cryptonote_config.h" namespace nodetool @@ -84,6 +85,15 @@ namespace nodetool KV_SERIALIZE_OPT(rpc_port, (uint16_t)0) KV_SERIALIZE_OPT(rpc_credits_per_hash, (uint32_t)0) END_KV_SERIALIZE_MAP() + + BEGIN_SERIALIZE() + FIELD(adr) + FIELD(id) + VARINT_FIELD(last_seen) + VARINT_FIELD(pruning_seed) + VARINT_FIELD(rpc_port) + VARINT_FIELD(rpc_credits_per_hash) + END_SERIALIZE() }; typedef peerlist_entry_base<epee::net_utils::network_address> peerlist_entry; @@ -99,6 +109,12 @@ namespace nodetool KV_SERIALIZE(id) KV_SERIALIZE(first_seen) END_KV_SERIALIZE_MAP() + + BEGIN_SERIALIZE() + FIELD(adr) + FIELD(id) + VARINT_FIELD(first_seen) + END_SERIALIZE() }; typedef anchor_peerlist_entry_base<epee::net_utils::network_address> anchor_peerlist_entry; @@ -114,6 +130,12 @@ namespace nodetool KV_SERIALIZE(id) KV_SERIALIZE(is_income) END_KV_SERIALIZE_MAP() + + BEGIN_SERIALIZE() + FIELD(adr) + FIELD(id) + FIELD(is_income) + END_SERIALIZE() }; typedef connection_entry_base<epee::net_utils::network_address> connection_entry; diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 9b7f26a02..ce11981ad 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -49,7 +49,7 @@ extern "C" { #include "hex.h" #include "span.h" #include "memwipe.h" -#include "serialization/vector.h" +#include "serialization/containers.h" #include "serialization/debug_archive.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" @@ -239,6 +239,12 @@ namespace rct { struct RCTConfig { RangeProofType range_proof_type; int bp_version; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + VARINT_FIELD(range_proof_type) + VARINT_FIELD(bp_version) + END_SERIALIZE() }; struct rctSigBase { uint8_t type; @@ -317,6 +323,16 @@ namespace rct { ar.end_array(); return ar.stream().good(); } + + BEGIN_SERIALIZE_OBJECT() + FIELD(type) + FIELD(message) + FIELD(mixRing) + FIELD(pseudoOuts) + FIELD(ecdhInfo) + FIELD(outPk) + VARINT_FIELD(txnFee) + END_SERIALIZE() }; struct rctSigPrunable { std::vector<rangeSig> rangeSigs; @@ -436,6 +452,12 @@ namespace rct { return ar.stream().good(); } + BEGIN_SERIALIZE_OBJECT() + FIELD(rangeSigs) + FIELD(bulletproofs) + FIELD(MGs) + FIELD(pseudoOuts) + END_SERIALIZE() }; struct rctSig: public rctSigBase { rctSigPrunable p; @@ -449,6 +471,11 @@ namespace rct { { return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 ? p.pseudoOuts : pseudoOuts; } + + BEGIN_SERIALIZE_OBJECT() + FIELDS((rctSigBase&)*this) + FIELD(p) + END_SERIALIZE() }; //other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 62822cfa3..9e17bed63 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1120,11 +1120,23 @@ namespace cryptonote bool core_rpc_server::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res, const connection_context *ctx) { RPC_TRACKER(send_raw_tx); - bool ok; - if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_SEND_RAW_TX>(invoke_http_mode::JON, "/sendrawtransaction", req, res, ok)) - return ok; - CHECK_CORE_READY(); + const bool restricted = m_restricted && ctx; + + bool skip_validation = false; + if (!restricted) + { + boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex); + if (m_bootstrap_daemon.get() != nullptr) + { + skip_validation = !check_core_ready(); + } + else + { + CHECK_CORE_READY(); + } + } + CHECK_PAYMENT_MIN1(req, res, COST_PER_TX_RELAY, false); std::string tx_blob; @@ -1144,48 +1156,49 @@ namespace cryptonote } res.sanity_check_failed = false; - const bool restricted = m_restricted && ctx; - - tx_verification_context tvc{}; - if(!m_core.handle_incoming_tx({tx_blob, crypto::null_hash}, tvc, (req.do_not_relay ? relay_method::none : relay_method::local), false) || tvc.m_verifivation_failed) - { - res.status = "Failed"; - std::string reason = ""; - if ((res.low_mixin = tvc.m_low_mixin)) - add_reason(reason, "bad ring size"); - if ((res.double_spend = tvc.m_double_spend)) - add_reason(reason, "double spend"); - if ((res.invalid_input = tvc.m_invalid_input)) - add_reason(reason, "invalid input"); - if ((res.invalid_output = tvc.m_invalid_output)) - add_reason(reason, "invalid output"); - if ((res.too_big = tvc.m_too_big)) - add_reason(reason, "too big"); - if ((res.overspend = tvc.m_overspend)) - add_reason(reason, "overspend"); - if ((res.fee_too_low = tvc.m_fee_too_low)) - add_reason(reason, "fee too low"); - if ((res.too_few_outputs = tvc.m_too_few_outputs)) - add_reason(reason, "too few outputs"); - const std::string punctuation = reason.empty() ? "" : ": "; - if (tvc.m_verifivation_failed) - { - LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed" << punctuation << reason); + if (!skip_validation) + { + tx_verification_context tvc{}; + if(!m_core.handle_incoming_tx({tx_blob, crypto::null_hash}, tvc, (req.do_not_relay ? relay_method::none : relay_method::local), false) || tvc.m_verifivation_failed) + { + res.status = "Failed"; + std::string reason = ""; + if ((res.low_mixin = tvc.m_low_mixin)) + add_reason(reason, "bad ring size"); + if ((res.double_spend = tvc.m_double_spend)) + add_reason(reason, "double spend"); + if ((res.invalid_input = tvc.m_invalid_input)) + add_reason(reason, "invalid input"); + if ((res.invalid_output = tvc.m_invalid_output)) + add_reason(reason, "invalid output"); + if ((res.too_big = tvc.m_too_big)) + add_reason(reason, "too big"); + if ((res.overspend = tvc.m_overspend)) + add_reason(reason, "overspend"); + if ((res.fee_too_low = tvc.m_fee_too_low)) + add_reason(reason, "fee too low"); + if ((res.too_few_outputs = tvc.m_too_few_outputs)) + add_reason(reason, "too few outputs"); + const std::string punctuation = reason.empty() ? "" : ": "; + if (tvc.m_verifivation_failed) + { + LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed" << punctuation << reason); + } + else + { + LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx" << punctuation << reason); + } + return true; } - else + + if(tvc.m_relay == relay_method::none) { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx" << punctuation << reason); + LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed"); + res.reason = "Not relayed"; + res.not_relayed = true; + res.status = CORE_RPC_STATUS_OK; + return true; } - return true; - } - - if(tvc.m_relay == relay_method::none) - { - LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed"); - res.reason = "Not relayed"; - res.not_relayed = true; - res.status = CORE_RPC_STATUS_OK; - return true; } NOTIFY_NEW_TRANSACTIONS::request r; diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp index edc8f0dda..176f11fa3 100644 --- a/src/rpc/rpc_payment.cpp +++ b/src/rpc/rpc_payment.cpp @@ -27,14 +27,12 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <boost/archive/portable_binary_iarchive.hpp> -#include <boost/archive/portable_binary_oarchive.hpp> #include "cryptonote_config.h" #include "include_base_utils.h" #include "string_tools.h" #include "file_io_utils.h" #include "int-util.h" #include "common/util.h" -#include "serialization/crypto.h" #include "common/unordered_containers_boost_serialization.h" #include "cryptonote_basic/cryptonote_boost_serialization.h" #include "cryptonote_basic/cryptonote_format_utils.h" @@ -296,14 +294,28 @@ namespace cryptonote data.open(state_file_path, std::ios_base::binary | std::ios_base::in); if (!data.fail()) { + bool loaded = false; try { - boost::archive::portable_binary_iarchive a(data); - a >> *this; + binary_archive<false> ar(data); + if (::serialization::serialize(ar, *this)) + if (::serialization::check_stream_state(ar)) + loaded = true; } - catch (const std::exception &e) + catch (...) {} + if (!loaded) { - MERROR("Failed to load RPC payments file: " << e.what()); + try + { + boost::archive::portable_binary_iarchive a(data); + a >> *this; + loaded = true; + } + catch (...) {} + } + if (!loaded) + { + MERROR("Failed to load RPC payments file"); m_client_info.clear(); } } @@ -344,8 +356,9 @@ namespace cryptonote MWARNING("Failed to save RPC payments to file " << state_file_path); return false; }; - boost::archive::portable_binary_oarchive a(data); - a << *this; + binary_archive<true> ar(data); + if (!::serialization::serialize(ar, *const_cast<rpc_payment*>(this))) + return false; return true; CATCH_ENTRY_L0("rpc_payment::store", false); } diff --git a/src/rpc/rpc_payment.h b/src/rpc/rpc_payment.h index dcd43f8d5..fdf1f953f 100644 --- a/src/rpc/rpc_payment.h +++ b/src/rpc/rpc_payment.h @@ -31,10 +31,17 @@ #include <string> #include <unordered_set> #include <unordered_map> +#include <map> #include <boost/thread/mutex.hpp> #include <boost/serialization/version.hpp> #include "cryptonote_basic/blobdatatype.h" #include "cryptonote_basic/cryptonote_basic.h" +#include <boost/serialization/list.hpp> +#include <boost/serialization/vector.hpp> +#include "serialization/crypto.h" +#include "serialization/string.h" +#include "serialization/pair.h" +#include "serialization/containers.h" namespace cryptonote { @@ -96,6 +103,33 @@ namespace cryptonote a & nonces_bad; a & nonces_dupe; } + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(block) + FIELD(previous_block) + FIELD(hashing_blob) + FIELD(previous_hashing_blob) + VARINT_FIELD(seed_height) + VARINT_FIELD(previous_seed_height) + FIELD(seed_hash) + FIELD(previous_seed_hash) + VARINT_FIELD(cookie) + FIELD(top) + FIELD(previous_top) + VARINT_FIELD(credits) + FIELD(payments) + FIELD(previous_payments) + FIELD(update_time) + FIELD(last_request_timestamp) + FIELD(block_template_update_time) + VARINT_FIELD(credits_total) + VARINT_FIELD(credits_used) + VARINT_FIELD(nonces_good) + VARINT_FIELD(nonces_stale) + VARINT_FIELD(nonces_bad) + VARINT_FIELD(nonces_dupe) + END_SERIALIZE() }; public: @@ -114,8 +148,8 @@ namespace cryptonote template <class t_archive> inline void serialize(t_archive &a, const unsigned int ver) { - a & m_client_info; - a & m_hashrate; + a & m_client_info.parent(); + a & m_hashrate.parent(); a & m_credits_total; a & m_credits_used; a & m_nonces_good; @@ -124,6 +158,18 @@ namespace cryptonote a & m_nonces_dupe; } + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(m_client_info) + FIELD(m_hashrate) + VARINT_FIELD(m_credits_total) + VARINT_FIELD(m_credits_used) + VARINT_FIELD(m_nonces_good) + VARINT_FIELD(m_nonces_stale) + VARINT_FIELD(m_nonces_bad) + VARINT_FIELD(m_nonces_dupe) + END_SERIALIZE() + bool load(std::string directory); bool store(const std::string &directory = std::string()) const; @@ -131,9 +177,9 @@ namespace cryptonote cryptonote::account_public_address m_address; uint64_t m_diff; uint64_t m_credits_per_hash_found; - std::unordered_map<crypto::public_key, client_info> m_client_info; + serializable_unordered_map<crypto::public_key, client_info> m_client_info; std::string m_directory; - std::map<uint64_t, uint64_t> m_hashrate; + serializable_map<uint64_t, uint64_t> m_hashrate; uint64_t m_credits_total; uint64_t m_credits_used; uint64_t m_nonces_good; @@ -143,6 +189,3 @@ namespace cryptonote mutable boost::mutex mutex; }; } - -BOOST_CLASS_VERSION(cryptonote::rpc_payment, 0); -BOOST_CLASS_VERSION(cryptonote::rpc_payment::client_info, 0); diff --git a/src/serialization/container.h b/src/serialization/container.h index 4bf47ecfa..d5e75bb4f 100644 --- a/src/serialization/container.h +++ b/src/serialization/container.h @@ -28,10 +28,6 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers -#pragma once - -#include "serialization.h" - namespace serialization { namespace detail @@ -103,7 +99,7 @@ bool do_serialize_container(Archive<true> &ar, C &v) return false; if (i != v.begin()) ar.delimit_array(); - if(!::serialization::detail::serialize_container_element(ar, const_cast<typename C::value_type&>(*i))) + if(!::serialization::detail::serialize_container_element(ar, (typename C::value_type&)*i)) return false; if (!ar.stream().good()) return false; diff --git a/src/serialization/containers.h b/src/serialization/containers.h new file mode 100644 index 000000000..bc4a89527 --- /dev/null +++ b/src/serialization/containers.h @@ -0,0 +1,128 @@ +// Copyright (c) 2014-2019, 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 <vector> +#include <deque> +#include <unordered_map> +#include <map> +#include <unordered_set> +#include <set> +#include "serialization.h" + +template <template <bool> class Archive, class T> 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); + +template<typename K, typename V> +class serializable_unordered_map: public std::unordered_map<K, V> +{ +public: + typedef typename std::pair<K, V> value_type; + typename std::unordered_map<K, V> &parent() { return *this; } +}; + +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_map<K, V> &v); +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_map<K, V> &v); + +template<typename K, typename V> +class serializable_map: public std::map<K, V> +{ +public: + typedef typename std::pair<K, V> value_type; + typename std::map<K, V> &parent() { return *this; } +}; + +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_map<K, V> &v); +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_map<K, V> &v); + +template<typename K, typename V> +class serializable_unordered_multimap: public std::unordered_multimap<K, V> +{ +public: + typedef typename std::pair<K, V> value_type; + typename std::unordered_multimap<K, V> &parent() { return *this; } +}; + +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_multimap<K, V> &v); +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_multimap<K, V> &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); + +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); + +namespace serialization +{ + namespace detail + { + template <typename T> void do_reserve(std::vector<T> &c, size_t N) { c.reserve(N); } + template <typename T> void do_add(std::vector<T> &c, T &&e) { c.emplace_back(std::forward<T>(e)); } + + template <typename T> void do_add(std::deque<T> &c, T &&e) { c.emplace_back(std::forward<T>(e)); } + + template <typename K, typename V> void do_add(serializable_unordered_map<K, V> &c, std::pair<K, V> &&e) { c.insert(std::forward<std::pair<K, V>>(e)); } + + template <typename K, typename V> void do_add(serializable_map<K, V> &c, std::pair<K, V> &&e) { c.insert(std::forward<std::pair<K, V>>(e)); } + + template <typename K, typename V> void do_add(serializable_unordered_multimap<K, V> &c, std::pair<K, V> &&e) { c.insert(std::forward<std::pair<K, V>>(e)); } + + template <typename T> void do_add(std::unordered_set<T> &c, T &&e) { c.insert(std::forward<T>(e)); } + + template <typename T> void do_add(std::set<T> &c, T &&e) { c.insert(std::forward<T>(e)); } + } +} + +#include "container.h" + +template <template <bool> class Archive, class T> 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_container(ar, v); } + +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); } + +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_map<K, V> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_map<K, V> &v) { return do_serialize_container(ar, v); } + +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_map<K, V> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_map<K, V> &v) { return do_serialize_container(ar, v); } + +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<false> &ar, serializable_unordered_multimap<K, V> &v) { return do_serialize_container(ar, v); } +template <template <bool> class Archive, typename K, typename V> bool do_serialize(Archive<true> &ar, serializable_unordered_multimap<K, V> &v) { return do_serialize_container(ar, v); } + +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); } + +template <template <bool> class Archive, class T> 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_container(ar, v); } diff --git a/src/serialization/deque.h b/src/serialization/deque.h deleted file mode 100644 index b029ed430..000000000 --- a/src/serialization/deque.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2014-2020, 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 <deque> - -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 T> - void do_reserve(std::deque<T> &c, size_t N) - { - c.reserve(N); - } - - template <typename T> - void do_add(std::deque<T> &c, T &&e) - { - c.emplace_back(std::move(e)); - } - } -} - -#include "serialization.h" - -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); } - diff --git a/src/serialization/list.h b/src/serialization/list.h index 139269b40..411e7800d 100644 --- a/src/serialization/list.h +++ b/src/serialization/list.h @@ -44,7 +44,7 @@ namespace serialization template <typename T> void do_add(std::list<T> &c, T &&e) { - c.emplace_back(std::move(e)); + c.emplace_back(std::forward<T>(e)); } } } diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index d0f9ee0f7..3ebeed171 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -48,6 +48,7 @@ #include <string> #include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/integral_constant.hpp> +#include <boost/mpl/bool.hpp> /*! \struct is_blob_type * @@ -278,6 +279,27 @@ inline bool do_serialize(Archive &ar, bool &v) if (!ar.stream().good()) return false; \ } while(0); +/*! \macro MAGIC_FIELD(m) + */ +#define MAGIC_FIELD(m) \ + std::string magic = m; \ + do { \ + ar.tag("magic"); \ + ar.serialize_blob((void*)magic.data(), magic.size()); \ + if (!ar.stream().good()) return false; \ + if (magic != m) return false; \ + } while(0); + +/*! \macro VERSION_FIELD(v) + */ +#define VERSION_FIELD(v) \ + uint32_t version = v; \ + do { \ + ar.tag("version"); \ + ar.serialize_varint(version); \ + if (!ar.stream().good()) return false; \ + } while(0); + namespace serialization { /*! \namespace detail diff --git a/src/serialization/set.h b/src/serialization/set.h deleted file mode 100644 index 157c002f7..000000000 --- a/src/serialization/set.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2014-2020, 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::set<T> &v); -template <template <bool> class Archive, class T> -bool do_serialize(Archive<true> &ar, std::set<T> &v); - -namespace serialization -{ - namespace detail - { - template <typename T> - void do_add(std::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::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_container(ar, v); } - diff --git a/src/serialization/unordered_set.h b/src/serialization/unordered_set.h deleted file mode 100644 index 24aa09437..000000000 --- a/src/serialization/unordered_set.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2014-2020, 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 deleted file mode 100644 index 1fca1d485..000000000 --- a/src/serialization/vector.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2014-2020, 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 <vector> -#include "serialization.h" - -template <template <bool> class Archive, class T> -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); - -namespace serialization -{ - namespace detail - { - template <typename T> - void do_reserve(std::vector<T> &c, size_t N) - { - c.reserve(N); - } - - template <typename T> - void do_add(std::vector<T> &c, T &&e) - { - c.emplace_back(std::move(e)); - } - } -} - -#include "container.h" - -template <template <bool> class Archive, class T> -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_container(ar, v); } - diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 69c684097..02540a844 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -208,7 +208,7 @@ namespace const char* USAGE_ADDRESS_BOOK("address_book [(add (<address>|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]"); const char* USAGE_SET_VARIABLE("set <option> [<value>]"); const char* USAGE_GET_TX_KEY("get_tx_key <txid>"); - const char* USAGE_SET_TX_KEY("set_tx_key <txid> <tx_key>"); + const char* USAGE_SET_TX_KEY("set_tx_key <txid> <tx_key> [<subaddress>]"); const char* USAGE_CHECK_TX_KEY("check_tx_key <txid> <txkey> <address>"); const char* USAGE_GET_TX_PROOF("get_tx_proof <txid> <address> [<message>]"); const char* USAGE_CHECK_TX_PROOF("check_tx_proof <txid> <address> <signature_file> [<message>]"); @@ -3100,6 +3100,28 @@ bool simple_wallet::set_export_format(const std::vector<std::string> &args/* = s return true; } +bool simple_wallet::set_load_deprecated_formats(const std::vector<std::string> &args/* = std::vector<std::string()*/) +{ + if (args.size() < 2) + { + fail_msg_writer() << tr("Value not specified"); + return true; + } + + const auto pwd_container = get_and_verify_password(); + if (pwd_container) + { + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->load_deprecated_formats(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + + if (r) + message_writer() << tr("Warning: deprecated formats use boost serialization, which has buffer overflows and crashers. Only load deprecated formats from sources you trust."); + }); + } + return true; +} + bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { if(args.empty()) @@ -3789,6 +3811,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) success_msg_writer() << "persistent-rpc-client-id = " << m_wallet->persistent_rpc_client_id(); success_msg_writer() << "auto-mine-for-rpc-payment-threshold = " << m_wallet->auto_mine_for_rpc_payment_threshold(); success_msg_writer() << "credits-target = " << m_wallet->credits_target(); + success_msg_writer() << "load-deprecated-formats = " << m_wallet->load_deprecated_formats(); return true; } else @@ -3850,6 +3873,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no")); CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>")); CHECK_SIMPLE_VARIABLE("export-format", set_export_format, tr("\"binary\" or \"ascii\"")); + CHECK_SIMPLE_VARIABLE("load-deprecated-formats", set_load_deprecated_formats, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("persistent-rpc-client-id", set_persistent_rpc_client_id, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("auto-mine-for-rpc-payment-threshold", set_auto_mine_for_rpc_payment_threshold, tr("floating point >= 0")); CHECK_SIMPLE_VARIABLE("credits-target", set_credits_target, tr("unsigned integer")); @@ -7939,11 +7963,27 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_) { std::vector<std::string> local_args = args_; - if(local_args.size() != 2) { + if(local_args.size() != 2 && local_args.size() != 3) { PRINT_USAGE(USAGE_SET_TX_KEY); return true; } + boost::optional<cryptonote::account_public_address> single_destination_subaddress; + if (local_args.size() > 1) + { + cryptonote::address_parse_info info; + if (cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args.back(), oa_prompter)) + { + if (!info.is_subaddress) + { + fail_msg_writer() << tr("Last argument is an address, but not a subaddress"); + return true; + } + single_destination_subaddress = info.address; + local_args.pop_back(); + } + } + crypto::hash txid; if (!epee::string_tools::hex_to_pod(local_args[0], txid)) { @@ -7983,12 +8023,14 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_) try { - m_wallet->set_tx_key(txid, tx_key, additional_tx_keys); + m_wallet->set_tx_key(txid, tx_key, additional_tx_keys, single_destination_subaddress); success_msg_writer() << tr("Tx key successfully stored."); } catch (const std::exception &e) { fail_msg_writer() << tr("Failed to store tx key: ") << e.what(); + if (!single_destination_subaddress) + fail_msg_writer() << tr("It could be because the transfer was to a subaddress. If this is the case, pass the subaddress last"); } return true; } diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 60aa6c4f6..5846fe056 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -151,6 +151,7 @@ namespace cryptonote bool set_setup_background_mining(const std::vector<std::string> &args = std::vector<std::string>()); bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>()); bool set_export_format(const std::vector<std::string> &args = std::vector<std::string>()); + bool set_load_deprecated_formats(const std::vector<std::string> &args = std::vector<std::string>()); bool set_persistent_rpc_client_id(const std::vector<std::string> &args = std::vector<std::string>()); bool set_auto_mine_for_rpc_payment_threshold(const std::vector<std::string> &args = std::vector<std::string>()); bool set_credits_target(const std::vector<std::string> &args = std::vector<std::string>()); diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp index fb07b42f0..303b576c7 100644 --- a/src/wallet/message_store.cpp +++ b/src/wallet/message_store.cpp @@ -27,7 +27,6 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "message_store.h" -#include <boost/archive/portable_binary_oarchive.hpp> #include <boost/archive/portable_binary_iarchive.hpp> #include <boost/format.hpp> #include <boost/algorithm/string.hpp> @@ -182,8 +181,8 @@ bool message_store::signer_labels_complete() const void message_store::get_signer_config(std::string &signer_config) { std::stringstream oss; - boost::archive::portable_binary_oarchive ar(oss); - ar << m_signers; + binary_archive<true> ar(oss); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, m_signers), tools::error::wallet_internal_error, "Failed to serialize signer config"); signer_config = oss.str(); } @@ -194,8 +193,8 @@ void message_store::unpack_signer_config(const multisig_wallet_state &state, con { std::stringstream iss; iss << signer_config; - boost::archive::portable_binary_iarchive ar(iss); - ar >> signers; + binary_archive<false> ar(iss); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, signers), tools::error::wallet_internal_error, "Failed to serialize signer config"); } catch (...) { @@ -364,8 +363,8 @@ size_t message_store::add_auto_config_data_message(const multisig_wallet_state & data.monero_address = me.monero_address; std::stringstream oss; - boost::archive::portable_binary_oarchive ar(oss); - ar << data; + binary_archive<true> ar(oss); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, data), tools::error::wallet_internal_error, "Failed to serialize auto config data"); return add_message(state, 0, message_type::auto_config_data, message_direction::out, oss.str()); } @@ -384,8 +383,8 @@ void message_store::process_auto_config_data_message(uint32_t id) { std::stringstream iss; iss << m.content; - boost::archive::portable_binary_iarchive ar(iss); - ar >> data; + binary_archive<false> ar(iss); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, data), tools::error::wallet_internal_error, "Failed to serialize auto config data"); } catch (...) { @@ -745,8 +744,8 @@ std::string message_store::get_sanitized_text(const std::string &text, size_t ma void message_store::write_to_file(const multisig_wallet_state &state, const std::string &filename) { std::stringstream oss; - boost::archive::portable_binary_oarchive ar(oss); - ar << *this; + binary_archive<true> ar(oss); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, *this), tools::error::wallet_internal_error, "Failed to serialize MMS state"); std::string buf = oss.str(); crypto::chacha_key key; @@ -762,14 +761,14 @@ void message_store::write_to_file(const multisig_wallet_state &state, const std: write_file_data.encrypted_data = encrypted_data; std::stringstream file_oss; - boost::archive::portable_binary_oarchive file_ar(file_oss); - file_ar << write_file_data; + binary_archive<true> file_ar(file_oss); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(file_ar, write_file_data), tools::error::wallet_internal_error, "Failed to serialize MMS state"); bool success = epee::file_io_utils::save_string_to_file(filename, file_oss.str()); THROW_WALLET_EXCEPTION_IF(!success, tools::error::file_save_error, filename); } -void message_store::read_from_file(const multisig_wallet_state &state, const std::string &filename) +void message_store::read_from_file(const multisig_wallet_state &state, const std::string &filename, bool load_deprecated_formats) { boost::system::error_code ignored_ec; bool file_exists = boost::filesystem::exists(filename, ignored_ec); @@ -785,17 +784,37 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std bool success = epee::file_io_utils::load_file_to_string(filename, buf); THROW_WALLET_EXCEPTION_IF(!success, tools::error::file_read_error, filename); + bool loaded = false; file_data read_file_data; try { std::stringstream iss; iss << buf; - boost::archive::portable_binary_iarchive ar(iss); - ar >> read_file_data; + binary_archive<false> ar(iss); + if (::serialization::serialize(ar, read_file_data)) + if (::serialization::check_stream_state(ar)) + loaded = true; } - catch (const std::exception &e) + catch (...) {} + if (!loaded && load_deprecated_formats) + { + try + { + std::stringstream iss; + iss << buf; + boost::archive::portable_binary_iarchive ar(iss); + ar >> read_file_data; + loaded = true; + } + catch (const std::exception &e) + { + MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>: " << e.what()); + THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename); + } + } + if (!loaded) { - MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>: " << e.what()); + MERROR("MMS file " << filename << " has bad structure <iv,encrypted_data>"); THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename); } @@ -805,16 +824,36 @@ void message_store::read_from_file(const multisig_wallet_state &state, const std decrypted_data.resize(read_file_data.encrypted_data.size()); crypto::chacha20(read_file_data.encrypted_data.data(), read_file_data.encrypted_data.size(), key, read_file_data.iv, &decrypted_data[0]); + loaded = false; try { std::stringstream iss; iss << decrypted_data; - boost::archive::portable_binary_iarchive ar(iss); - ar >> *this; + binary_archive<false> ar(iss); + if (::serialization::serialize(ar, *this)) + if (::serialization::check_stream_state(ar)) + loaded = true; } - catch (const std::exception &e) + catch(...) {} + if (!loaded && load_deprecated_formats) + { + try + { + std::stringstream iss; + iss << decrypted_data; + boost::archive::portable_binary_iarchive ar(iss); + ar >> *this; + loaded = true; + } + catch (const std::exception &e) + { + MERROR("MMS file " << filename << " has bad structure: " << e.what()); + THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename); + } + } + if (!loaded) { - MERROR("MMS file " << filename << " has bad structure: " << e.what()); + MERROR("MMS file " << filename << " has bad structure"); THROW_WALLET_EXCEPTION_IF(true, tools::error::file_read_error, filename); } diff --git a/src/wallet/message_store.h b/src/wallet/message_store.h index 9055fd776..0f53587d4 100644 --- a/src/wallet/message_store.h +++ b/src/wallet/message_store.h @@ -44,6 +44,9 @@ #include "common/command_line.h" #include "wipeable_string.h" #include "net/abstract_http_client.h" +#include "serialization/crypto.h" +#include "serialization/string.h" +#include "serialization/containers.h" #include "message_transporter.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -112,6 +115,24 @@ namespace mms uint32_t round; uint32_t signature_count; std::string transport_id; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + VARINT_FIELD(id) + VARINT_FIELD(type) + VARINT_FIELD(direction) + FIELD(content) + VARINT_FIELD(created) + VARINT_FIELD(modified) + VARINT_FIELD(sent) + VARINT_FIELD(signer_index) + FIELD(hash) + VARINT_FIELD(state) + VARINT_FIELD(wallet_height) + VARINT_FIELD(round) + VARINT_FIELD(signature_count) + FIELD(transport_id) + END_SERIALIZE() }; // "wallet_height" (for lack of a short name that would describe what it is about) // is the number of transfers present in the wallet at the time of message @@ -132,6 +153,21 @@ namespace mms std::string auto_config_transport_address; bool auto_config_running; + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(label) + FIELD(transport_address) + FIELD(monero_address_known) + FIELD(monero_address) + FIELD(me) + VARINT_FIELD(index) + FIELD(auto_config_token) + FIELD(auto_config_public_key) + FIELD(auto_config_secret_key) + FIELD(auto_config_transport_address) + FIELD(auto_config_running) + END_SERIALIZE() + authorized_signer() { monero_address_known = false; @@ -164,6 +200,13 @@ namespace mms std::string label; std::string transport_address; cryptonote::account_public_address monero_address; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(label) + FIELD(transport_address) + FIELD(monero_address) + END_SERIALIZE() }; // Overal .mms file structure, with the "message_store" object serialized to and @@ -174,6 +217,13 @@ namespace mms uint32_t file_version; crypto::chacha_iv iv; std::string encrypted_data; + + BEGIN_SERIALIZE_OBJECT() + FIELD(magic_string) + FIELD(file_version) + FIELD(iv) + FIELD(encrypted_data) + END_SERIALIZE() }; // The following struct provides info about the current state of a "wallet2" object @@ -198,6 +248,19 @@ namespace mms uint32_t multisig_rounds_passed; size_t num_transfer_details; std::string mms_file; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(address) + VARINT_FIELD(nettype) + FIELD(view_secret_key) + FIELD(multisig) + FIELD(multisig_is_ready) + FIELD(has_multisig_partial_key_images) + VARINT_FIELD(multisig_rounds_passed) + VARINT_FIELD(num_transfer_details) + FIELD(mms_file) + END_SERIALIZE() }; class message_store @@ -283,7 +346,7 @@ namespace mms void stop() { m_run.store(false, std::memory_order_relaxed); m_transporter.stop(); } void write_to_file(const multisig_wallet_state &state, const std::string &filename); - void read_from_file(const multisig_wallet_state &state, const std::string &filename); + void read_from_file(const multisig_wallet_state &state, const std::string &filename, bool load_deprecated_formats = false); template <class t_archive> inline void serialize(t_archive &a, const unsigned int ver) @@ -298,6 +361,18 @@ namespace mms a & m_auto_send; } + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(m_active) + VARINT_FIELD(m_num_authorized_signers) + VARINT_FIELD(m_nettype) + VARINT_FIELD(m_num_required_signers) + FIELD(m_signers) + FIELD(m_messages) + VARINT_FIELD(m_next_message_id) + FIELD(m_auto_send) + END_SERIALIZE() + static const char* message_type_to_string(message_type type); static const char* message_direction_to_string(message_direction direction); static const char* message_state_to_string(message_state state); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 18072f350..5d78bb7b0 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -103,8 +103,8 @@ using namespace cryptonote; // used to target a given block weight (additional outputs may be added on top to build fee) #define TX_WEIGHT_TARGET(bytes) (bytes*2/3) -#define UNSIGNED_TX_PREFIX "Monero unsigned tx set\004" -#define SIGNED_TX_PREFIX "Monero signed tx set\004" +#define UNSIGNED_TX_PREFIX "Monero unsigned tx set\005" +#define SIGNED_TX_PREFIX "Monero signed tx set\005" #define MULTISIG_UNSIGNED_TX_PREFIX "Monero multisig unsigned tx set\001" #define RECENT_OUTPUT_RATIO (0.5) // 50% of outputs are from the recent zone @@ -1183,6 +1183,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_offline(false), m_rpc_version(0), m_export_format(ExportFormat::Binary), + m_load_deprecated_formats(false), m_credits_target(0) { set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); @@ -3903,6 +3904,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee: value2.SetInt(m_export_format); json.AddMember("export_format", value2, json.GetAllocator()); + value2.SetInt(m_load_deprecated_formats); + json.AddMember("load_deprecated_formats", value2, json.GetAllocator()); + value2.SetUint(1); json.AddMember("encrypted_secret_keys", value2, json.GetAllocator()); @@ -4072,6 +4076,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR; m_original_keys_available = false; m_export_format = ExportFormat::Binary; + m_load_deprecated_formats = false; m_device_name = ""; m_device_derivation_path = ""; m_key_device_type = hw::device::device_type::SOFTWARE; @@ -4252,6 +4257,9 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, export_format, ExportFormat, Int, false, Binary); m_export_format = field_export_format; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, load_deprecated_formats, int, Int, false, false); + m_load_deprecated_formats = field_load_deprecated_formats; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string()); if (m_device_name.empty()) { @@ -5045,7 +5053,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor m_account.finalize_multisig(spend_public_key); m_multisig_signers = signers; - std::sort(m_multisig_signers.begin(), m_multisig_signers.end(), [](const crypto::public_key &e0, const crypto::public_key &e1){ return memcmp(&e0, &e1, sizeof(e0)); }); + std::sort(m_multisig_signers.begin(), m_multisig_signers.end(), [](const crypto::public_key &e0, const crypto::public_key &e1){ return memcmp(&e0, &e1, sizeof(e0)) < 0; }); ++m_multisig_rounds_passed; m_multisig_derivations.clear(); @@ -5601,10 +5609,26 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]); try { - std::stringstream iss; - iss << cache_data; - boost::archive::portable_binary_iarchive ar(iss); - ar >> *this; + bool loaded = false; + + try + { + std::stringstream iss; + iss << cache_data; + binary_archive<false> ar(iss); + if (::serialization::serialize(ar, *this)) + if (::serialization::check_stream_state(ar)) + loaded = true; + } + catch(...) { } + + if (!loaded) + { + std::stringstream iss; + iss << cache_data; + boost::archive::portable_binary_iarchive ar(iss); + ar >> *this; + } } catch(...) { @@ -5701,7 +5725,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass try { if (use_fs) - m_message_store.read_from_file(get_multisig_wallet_state(), m_mms_file); + m_message_store.read_from_file(get_multisig_wallet_state(), m_mms_file, m_load_deprecated_formats); } catch (const std::exception &e) { @@ -5891,8 +5915,9 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data(const epe try { std::stringstream oss; - boost::archive::portable_binary_oarchive ar(oss); - ar << *this; + binary_archive<true> ar(oss); + if (!::serialization::serialize(ar, *this)) + return boost::none; boost::optional<wallet2::cache_file_data> cache_file_data = (wallet2::cache_file_data) {}; cache_file_data.get().cache_data = oss.str(); @@ -6499,8 +6524,8 @@ void wallet2::commit_tx(pending_tx& ptx) add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount, ptx.construction_data.subaddr_account, ptx.construction_data.subaddr_indices); if (store_tx_info() && ptx.tx_key != crypto::null_skey) { - m_tx_keys.insert(std::make_pair(txid, ptx.tx_key)); - m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys)); + m_tx_keys[txid] = ptx.tx_key; + m_additional_tx_keys[txid] = ptx.additional_tx_keys; } LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]"); @@ -6554,10 +6579,11 @@ std::string wallet2::dump_tx_to_str(const std::vector<pending_tx> &ptx_vector) c txs.transfers = export_outputs(); // save as binary std::ostringstream oss; - boost::archive::portable_binary_oarchive ar(oss); + binary_archive<true> ar(oss); try { - ar << txs; + if (!::serialization::serialize(ar, txs)) + return std::string(); } catch (...) { @@ -6601,6 +6627,11 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi s = s.substr(1); if (version == '\003') { + if (!m_load_deprecated_formats) + { + LOG_PRINT_L0("Not loading deprecated format"); + return false; + } try { std::istringstream iss(s); @@ -6615,6 +6646,11 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi } else if (version == '\004') { + if (!m_load_deprecated_formats) + { + LOG_PRINT_L0("Not loading deprecated format"); + return false; + } try { s = decrypt_with_view_secret_key(s); @@ -6636,6 +6672,26 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi return false; } } + else if (version == '\005') + { + try { s = decrypt_with_view_secret_key(s); } + catch(const std::exception &e) { LOG_PRINT_L0("Failed to decrypt unsigned tx: " << e.what()); return false; } + try + { + std::istringstream iss(s); + binary_archive<false> ar(iss); + if (!::serialization::serialize(ar, exported_txs)) + { + LOG_PRINT_L0("Failed to parse data from unsigned tx"); + return false; + } + } + catch (...) + { + LOG_PRINT_L0("Failed to parse data from unsigned tx"); + return false; + } + } else { LOG_PRINT_L0("Unsupported version in unsigned tx"); @@ -6689,8 +6745,8 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin if (store_tx_info() && tx_key != crypto::null_skey) { const crypto::hash txid = get_transaction_hash(ptx.tx); - m_tx_keys.insert(std::make_pair(txid, tx_key)); - m_additional_tx_keys.insert(std::make_pair(txid, additional_tx_keys)); + m_tx_keys[txid] = tx_key; + m_additional_tx_keys[txid] = additional_tx_keys; } std::string key_images; @@ -6833,10 +6889,11 @@ std::string wallet2::sign_tx_dump_to_str(unsigned_tx_set &exported_txs, std::vec // save as binary std::ostringstream oss; - boost::archive::portable_binary_oarchive ar(oss); + binary_archive<true> ar(oss); try { - ar << signed_txes; + if (!::serialization::serialize(ar, signed_txes)) + return std::string(); } catch(...) { @@ -6885,6 +6942,11 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too s = s.substr(1); if (version == '\003') { + if (!m_load_deprecated_formats) + { + LOG_PRINT_L0("Not loading deprecated format"); + return false; + } try { std::istringstream iss(s); @@ -6899,6 +6961,11 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too } else if (version == '\004') { + if (!m_load_deprecated_formats) + { + LOG_PRINT_L0("Not loading deprecated format"); + return false; + } try { s = decrypt_with_view_secret_key(s); @@ -6920,6 +6987,26 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too return false; } } + else if (version == '\005') + { + try { s = decrypt_with_view_secret_key(s); } + catch (const std::exception &e) { LOG_PRINT_L0("Failed to decrypt signed transaction: " << e.what()); return false; } + try + { + std::istringstream iss(s); + binary_archive<false> ar(iss); + if (!::serialization::serialize(ar, signed_txs)) + { + LOG_PRINT_L0("Failed to deserialize signed transaction"); + return false; + } + } + catch (const std::exception &e) + { + LOG_PRINT_L0("Failed to decrypt signed transaction: " << e.what()); + return false; + } + } else { LOG_PRINT_L0("Unsupported version in signed transaction"); @@ -6971,10 +7058,11 @@ std::string wallet2::save_multisig_tx(multisig_tx_set txs) // save as binary std::ostringstream oss; - boost::archive::portable_binary_oarchive ar(oss); + binary_archive<true> ar(oss); try { - ar << txs; + if (!::serialization::serialize(ar, txs)) + return std::string(); } catch (...) { @@ -7038,13 +7126,29 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx LOG_PRINT_L0("Failed to decrypt multisig tx data: " << e.what()); return false; } + bool loaded = false; try { std::istringstream iss(multisig_tx_st); - boost::archive::portable_binary_iarchive ar(iss); - ar >> exported_txs; + binary_archive<false> ar(iss); + if (::serialization::serialize(ar, exported_txs)) + if (::serialization::check_stream_state(ar)) + loaded = true; } - catch (...) + catch (...) {} + try + { + if (!loaded && m_load_deprecated_formats) + { + std::istringstream iss(multisig_tx_st); + boost::archive::portable_binary_iarchive ar(iss); + ar >> exported_txs; + loaded = true; + } + } + catch(...) {} + + if (!loaded) { LOG_PRINT_L0("Failed to parse multisig tx data"); return false; @@ -7090,8 +7194,8 @@ bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported const crypto::hash txid = get_transaction_hash(ptx.tx); if (store_tx_info()) { - m_tx_keys.insert(std::make_pair(txid, ptx.tx_key)); - m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys)); + m_tx_keys[txid] = ptx.tx_key; + m_additional_tx_keys[txid] = ptx.additional_tx_keys; } } } @@ -7211,8 +7315,8 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto const crypto::hash txid = get_transaction_hash(ptx.tx); if (store_tx_info()) { - m_tx_keys.insert(std::make_pair(txid, ptx.tx_key)); - m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys)); + m_tx_keys[txid] = ptx.tx_key; + m_additional_tx_keys[txid] = ptx.additional_tx_keys; } txids.push_back(txid); } @@ -7447,7 +7551,7 @@ uint32_t wallet2::adjust_priority(uint32_t priority) getbh_req.client = get_client_signature(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "getblockheadersrange", getbh_req, getbh_res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, getbh_res, "getblockheadersrange", error::get_blocks_error, get_rpc_status(getbh_res.status)); - check_rpc_cost("/sendrawtransaction", getbh_res.credits, pre_call_credits, N * COST_PER_BLOCK_HEADER); + check_rpc_cost("/getblockheadersrange", getbh_res.credits, pre_call_credits, N * COST_PER_BLOCK_HEADER); } if (getbh_res.headers.size() != N) @@ -9531,8 +9635,8 @@ bool wallet2::light_wallet_parse_rct_str(const std::string& rct_string, const cr bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image, const crypto::public_key& tx_public_key, uint64_t out_index) { // Lookup key image from cache - std::map<uint64_t, crypto::key_image> index_keyimage_map; - std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> >::const_iterator found_pub_key = m_key_image_cache.find(tx_public_key); + serializable_map<uint64_t, crypto::key_image> index_keyimage_map; + serializable_unordered_map<crypto::public_key, serializable_map<uint64_t, crypto::key_image> >::const_iterator found_pub_key = m_key_image_cache.find(tx_public_key); if(found_pub_key != m_key_image_cache.end()) { // pub key found. key image for index cached? index_keyimage_map = found_pub_key->second; @@ -10902,7 +11006,7 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s return true; } //---------------------------------------------------------------------------------------------------- -void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys) +void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const boost::optional<cryptonote::account_public_address> &single_destination_subaddress) { // fetch tx from daemon and check if secret keys agree with corresponding public keys COMMAND_RPC_GET_TRANSACTIONS::request req = AUTO_VAL_INIT(req); @@ -10943,13 +11047,23 @@ void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_ found = true; break; } + // when sent to a single subaddress, the derivation is different + if (single_destination_subaddress) + { + calculated_pub_key = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(single_destination_subaddress->m_spend_public_key), rct::sk2rct(tx_key))); + if (calculated_pub_key == pub_key_field.pub_key) + { + found = true; + break; + } + } } THROW_WALLET_EXCEPTION_IF(!found, error::wallet_internal_error, "Given tx secret key doesn't agree with the tx public key in the blockchain"); tx_extra_additional_pub_keys additional_tx_pub_keys; find_tx_extra_field_by_type(tx_extra_fields, additional_tx_pub_keys); THROW_WALLET_EXCEPTION_IF(additional_tx_keys.size() != additional_tx_pub_keys.data.size(), error::wallet_internal_error, "The number of additional tx secret keys doesn't agree with the number of additional tx public keys in the blockchain" ); - m_tx_keys.insert(std::make_pair(txid, tx_key)); - m_additional_tx_keys.insert(std::make_pair(txid, additional_tx_keys)); + m_tx_keys[txid] = tx_key; + m_additional_tx_keys[txid] = additional_tx_keys; } //---------------------------------------------------------------------------------------------------- std::string wallet2::get_spend_proof(const crypto::hash &txid, const std::string &message) @@ -11720,7 +11834,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, } // collect all subaddress spend keys that received those outputs and generate their signatures - std::unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys; + serializable_unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys; for (const cryptonote::subaddress_index &index : subaddr_indices) { crypto::secret_key subaddr_spend_skey = m_account.get_keys().m_spend_secret_key; @@ -11737,8 +11851,9 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, // serialize & encode std::ostringstream oss; - boost::archive::portable_binary_oarchive ar(oss); - ar << proofs << subaddr_spendkeys; + binary_archive<true> ar(oss); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, proofs), error::wallet_internal_error, "Failed to serialize proof"); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, subaddr_spendkeys), error::wallet_internal_error, "Failed to serialize proof"); return "ReserveProofV2" + tools::base58::encode(oss.str()); } @@ -11762,11 +11877,25 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(std::strlen(header_v1)), sig_decoded), error::wallet_internal_error, "Signature decoding error"); - std::istringstream iss(sig_decoded); - boost::archive::portable_binary_iarchive ar(iss); + bool loaded = false; std::vector<reserve_proof_entry> proofs; - std::unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys; - ar >> proofs >> subaddr_spendkeys; + serializable_unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys; + try + { + std::istringstream iss(sig_decoded); + binary_archive<false> ar(iss); + if (::serialization::serialize_noeof(ar, proofs)) + if (::serialization::serialize_noeof(ar, subaddr_spendkeys)) + if (::serialization::check_stream_state(ar)) + loaded = true; + } + catch(...) {} + if (!loaded && m_load_deprecated_formats) + { + std::istringstream iss(sig_decoded); + boost::archive::portable_binary_iarchive ar(iss); + ar >> proofs >> subaddr_spendkeys.parent(); + } THROW_WALLET_EXCEPTION_IF(subaddr_spendkeys.count(address.m_spend_public_key) == 0, error::wallet_internal_error, "The given address isn't found in the proof"); @@ -12005,7 +12134,7 @@ std::string wallet2::get_description() const return ""; } -const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& wallet2::get_account_tags() +const std::pair<serializable_map<std::string, std::string>, std::vector<std::string>>& wallet2::get_account_tags() { // ensure consistency if (m_account_tags.second.size() != get_num_subaddress_accounts()) @@ -12727,9 +12856,9 @@ std::string wallet2::export_outputs_to_str(bool all) const PERF_TIMER(export_outputs_to_str); std::stringstream oss; - boost::archive::portable_binary_oarchive ar(oss); - const auto& outputs = export_outputs(all); - ar << outputs; + binary_archive<true> ar(oss); + auto outputs = export_outputs(all); + THROW_WALLET_EXCEPTION_IF(!::serialization::serialize(ar, outputs), error::wallet_internal_error, "Failed to serialize output data"); std::string magic(OUTPUT_EXPORT_FILE_MAGIC, strlen(OUTPUT_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; @@ -12841,23 +12970,39 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st) } size_t imported_outputs = 0; + bool loaded = false; try { std::string body(data, headerlen); - std::stringstream iss; - iss << body; std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs; try { - boost::archive::portable_binary_iarchive ar(iss); - ar >> outputs; + std::stringstream iss; + iss << body; + binary_archive<false> ar(iss); + if (::serialization::serialize(ar, outputs)) + if (::serialization::check_stream_state(ar)) + loaded = true; } - catch (...) + catch (...) {} + + if (!loaded && m_load_deprecated_formats) { - iss.str(""); - iss << body; - boost::archive::binary_iarchive ar(iss); - ar >> outputs; + try + { + std::stringstream iss; + iss << body; + boost::archive::portable_binary_iarchive ar(iss); + ar >> outputs; + loaded = true; + } + catch (...) {} + } + + if (!loaded) + { + outputs.first = 0; + outputs.second = {}; } imported_outputs = import_outputs(outputs); @@ -13011,8 +13156,8 @@ cryptonote::blobdata wallet2::export_multisig() } std::stringstream oss; - boost::archive::portable_binary_oarchive ar(oss); - ar << info; + binary_archive<true> ar(oss); + CHECK_AND_ASSERT_THROW_MES(::serialization::serialize(ar, info), "Failed to serialize multisig data"); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; std::string header; @@ -13082,10 +13227,26 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs) seen.insert(signer); std::string body(data, headerlen); - std::istringstream iss(body); std::vector<tools::wallet2::multisig_info> i; - boost::archive::portable_binary_iarchive ar(iss); - ar >> i; + + bool loaded = false; + try + { + std::istringstream iss(body); + binary_archive<false> ar(iss); + if (::serialization::serialize(ar, i)) + if (::serialization::check_stream_state(ar)) + loaded = true; + } + catch(...) {} + if (!loaded && m_load_deprecated_formats) + { + std::istringstream iss(body); + boost::archive::portable_binary_iarchive ar(iss); + ar >> i; + loaded = true; + } + CHECK_AND_ASSERT_THROW_MES(loaded, "Failed to load output data"); MINFO(boost::format("%u outputs found") % boost::lexical_cast<std::string>(i.size())); info.push_back(std::move(i)); } @@ -13123,7 +13284,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs) // sort by signer if (!info.empty() && !info.front().empty()) { - std::sort(info.begin(), info.end(), [](const std::vector<tools::wallet2::multisig_info> &i0, const std::vector<tools::wallet2::multisig_info> &i1){ return memcmp(&i0[0].m_signer, &i1[0].m_signer, sizeof(i0[0].m_signer)); }); + std::sort(info.begin(), info.end(), [](const std::vector<tools::wallet2::multisig_info> &i0, const std::vector<tools::wallet2::multisig_info> &i1){ return memcmp(&i0[0].m_signer, &i1[0].m_signer, sizeof(i0[0].m_signer)) < 0; }); } // first pass to determine where to detach the blockchain diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 4a10e3d23..f283a873e 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -34,6 +34,9 @@ #include <boost/program_options/options_description.hpp> #include <boost/program_options/variables_map.hpp> +#if BOOST_VERSION >= 107400 +#include <boost/serialization/library_version_type.hpp> +#endif #include <boost/serialization/list.hpp> #include <boost/serialization/vector.hpp> #include <boost/serialization/deque.hpp> @@ -57,7 +60,10 @@ #include "ringct/rctTypes.h" #include "ringct/rctOps.h" #include "checkpoints/checkpoints.h" +#include "serialization/crypto.h" +#include "serialization/string.h" #include "serialization/pair.h" +#include "serialization/containers.h" #include "wallet_errors.h" #include "common/password.h" @@ -205,6 +211,13 @@ private: a & m_blockchain; } + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + VARINT_FIELD(m_offset) + FIELD(m_genesis) + FIELD(m_blockchain) + END_SERIALIZE() + private: size_t m_offset; crypto::hash m_genesis; @@ -372,6 +385,19 @@ private: uint64_t m_timestamp; bool m_coinbase; cryptonote::subaddress_index m_subaddr_index; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(m_tx_hash) + VARINT_FIELD(m_amount) + FIELD(m_amounts) + VARINT_FIELD(m_fee) + VARINT_FIELD(m_block_height) + VARINT_FIELD(m_unlock_time) + VARINT_FIELD(m_timestamp) + FIELD(m_coinbase) + FIELD(m_subaddr_index) + END_SERIALIZE() }; struct address_tx : payment_details @@ -384,6 +410,12 @@ private: { payment_details m_pd; bool m_double_spend_seen; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(m_pd) + FIELD(m_double_spend_seen) + END_SERIALIZE() }; struct unconfirmed_transfer_details @@ -400,6 +432,21 @@ private: uint32_t m_subaddr_account; // subaddress account of your wallet to be used in this transfer std::set<uint32_t> m_subaddr_indices; // set of address indices used as inputs in this transfer std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> m_rings; // relative + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(m_tx) + VARINT_FIELD(m_amount_in) + VARINT_FIELD(m_amount_out) + VARINT_FIELD(m_change) + VARINT_FIELD(m_sent_time) + FIELD(m_dests) + FIELD(m_payment_id) + VARINT_FIELD(m_timestamp) + VARINT_FIELD(m_subaddr_account) + FIELD(m_subaddr_indices) + FIELD(m_rings) + END_SERIALIZE() }; struct confirmed_transfer_details @@ -419,6 +466,21 @@ private: confirmed_transfer_details(): m_amount_in(0), m_amount_out(0), m_change((uint64_t)-1), m_block_height(0), m_payment_id(crypto::null_hash), m_timestamp(0), m_unlock_time(0), m_subaddr_account((uint32_t)-1) {} confirmed_transfer_details(const unconfirmed_transfer_details &utd, uint64_t height): m_amount_in(utd.m_amount_in), m_amount_out(utd.m_amount_out), m_change(utd.m_change), m_block_height(height), m_dests(utd.m_dests), m_payment_id(utd.m_payment_id), m_timestamp(utd.m_timestamp), m_unlock_time(utd.m_tx.unlock_time), m_subaddr_account(utd.m_subaddr_account), m_subaddr_indices(utd.m_subaddr_indices), m_rings(utd.m_rings) {} + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + VARINT_FIELD(m_amount_in) + VARINT_FIELD(m_amount_out) + VARINT_FIELD(m_change) + VARINT_FIELD(m_block_height) + FIELD(m_dests) + FIELD(m_payment_id) + VARINT_FIELD(m_timestamp) + VARINT_FIELD(m_unlock_time) + VARINT_FIELD(m_subaddr_account) + FIELD(m_subaddr_indices) + FIELD(m_rings) + END_SERIALIZE() }; struct tx_construction_data @@ -451,7 +513,7 @@ private: }; typedef std::vector<transfer_details> transfer_container; - typedef std::unordered_multimap<crypto::hash, payment_details> payment_container; + typedef serializable_unordered_multimap<crypto::hash, payment_details> payment_container; struct multisig_sig { @@ -460,6 +522,15 @@ private: std::unordered_set<rct::key> used_L; std::unordered_set<crypto::public_key> signing_keys; rct::multisig_out msout; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(sigs) + FIELD(ignore) + FIELD(used_L) + FIELD(signing_keys) + FIELD(msout) + END_SERIALIZE() }; // The convention for destinations is: @@ -502,13 +573,26 @@ private: { std::vector<tx_construction_data> txes; std::pair<size_t, wallet2::transfer_container> transfers; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(txes) + FIELD(transfers) + END_SERIALIZE() }; struct signed_tx_set { std::vector<pending_tx> ptx; std::vector<crypto::key_image> key_images; - std::unordered_map<crypto::public_key, crypto::key_image> tx_key_images; + serializable_unordered_map<crypto::public_key, crypto::key_image> tx_key_images; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(ptx) + FIELD(key_images) + FIELD(tx_key_images) + END_SERIALIZE() }; struct multisig_tx_set @@ -543,7 +627,7 @@ private: FIELD(cache_data) END_SERIALIZE() }; - + // GUI Address book struct address_book_row { @@ -552,6 +636,15 @@ private: std::string m_description; bool m_is_subaddress; bool m_has_payment_id; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(m_address) + FIELD(m_payment_id) + FIELD(m_description) + FIELD(m_is_subaddress) + FIELD(m_has_payment_id) + END_SERIALIZE() }; struct reserve_proof_entry @@ -562,6 +655,16 @@ private: crypto::key_image key_image; crypto::signature shared_secret_sig; crypto::signature key_image_sig; + + BEGIN_SERIALIZE_OBJECT() + VERSION_FIELD(0) + FIELD(txid) + VARINT_FIELD(index_in_tx) + FIELD(shared_secret) + FIELD(key_image) + FIELD(shared_secret_sig) + FIELD(key_image_sig) + END_SERIALIZE() }; typedef std::tuple<uint64_t, crypto::public_key, rct::key> get_outs_entry; @@ -918,6 +1021,7 @@ private: { std::vector<crypto::hash> blockchain; a & blockchain; + m_blockchain.clear(); for (const auto &b: blockchain) { m_blockchain.push_back(b); @@ -929,25 +1033,25 @@ private: } a & m_transfers; a & m_account_public_address; - a & m_key_images; + a & m_key_images.parent(); if(ver < 6) return; - a & m_unconfirmed_txs; + a & m_unconfirmed_txs.parent(); if(ver < 7) return; - a & m_payments; + a & m_payments.parent(); if(ver < 8) return; - a & m_tx_keys; + a & m_tx_keys.parent(); if(ver < 9) return; - a & m_confirmed_txs; + a & m_confirmed_txs.parent(); if(ver < 11) return; a & dummy_refresh_height; if(ver < 12) return; - a & m_tx_notes; + a & m_tx_notes.parent(); if(ver < 13) return; if (ver < 17) @@ -955,6 +1059,7 @@ private: // we're loading an old version, where m_unconfirmed_payments was a std::map std::unordered_map<crypto::hash, payment_details> m; a & m; + m_unconfirmed_payments.clear(); for (std::unordered_map<crypto::hash, payment_details>::const_iterator i = m.begin(); i != m.end(); ++i) m_unconfirmed_payments.insert(std::make_pair(i->first, pool_payment_details{i->second, false})); } @@ -963,6 +1068,7 @@ private: if(ver < 15) { // we're loading an older wallet without a pubkey map, rebuild it + m_pub_keys.clear(); for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details &td = m_transfers[i]; @@ -972,7 +1078,7 @@ private: } return; } - a & m_pub_keys; + a & m_pub_keys.parent(); if(ver < 16) return; a & m_address_book; @@ -983,6 +1089,7 @@ private: // we're loading an old version, where m_unconfirmed_payments payload was payment_details std::unordered_multimap<crypto::hash, payment_details> m; a & m; + m_unconfirmed_payments.clear(); for (const auto &i: m) m_unconfirmed_payments.insert(std::make_pair(i.first, pool_payment_details{i.second, false})); } @@ -992,20 +1099,20 @@ private: a & m_scanned_pool_txs[1]; if (ver < 20) return; - a & m_subaddresses; + a & m_subaddresses.parent(); std::unordered_map<cryptonote::subaddress_index, crypto::public_key> dummy_subaddresses_inv; a & dummy_subaddresses_inv; a & m_subaddress_labels; - a & m_additional_tx_keys; + a & m_additional_tx_keys.parent(); if(ver < 21) return; - a & m_attributes; + a & m_attributes.parent(); if(ver < 22) return; - a & m_unconfirmed_payments; + a & m_unconfirmed_payments.parent(); if(ver < 23) return; - a & m_account_tags; + a & (std::pair<std::map<std::string, std::string>, std::vector<std::string>>&)m_account_tags; if(ver < 24) return; a & m_ring_history_saved; @@ -1014,18 +1121,48 @@ private: a & m_last_block_reward; if(ver < 26) return; - a & m_tx_device; + a & m_tx_device.parent(); if(ver < 27) return; a & m_device_last_key_image_sync; if(ver < 28) return; - a & m_cold_key_images; + a & m_cold_key_images.parent(); if(ver < 29) return; a & m_rpc_client_secret_key; } + BEGIN_SERIALIZE_OBJECT() + MAGIC_FIELD("monero wallet cache") + VERSION_FIELD(0) + FIELD(m_blockchain) + FIELD(m_transfers) + FIELD(m_account_public_address) + FIELD(m_key_images) + FIELD(m_unconfirmed_txs) + FIELD(m_payments) + FIELD(m_tx_keys) + FIELD(m_confirmed_txs) + FIELD(m_tx_notes) + FIELD(m_unconfirmed_payments) + FIELD(m_pub_keys) + FIELD(m_address_book) + FIELD(m_scanned_pool_txs[0]) + FIELD(m_scanned_pool_txs[1]) + FIELD(m_subaddresses) + FIELD(m_subaddress_labels) + FIELD(m_additional_tx_keys) + FIELD(m_attributes) + FIELD(m_account_tags) + FIELD(m_ring_history_saved) + FIELD(m_last_block_reward) + FIELD(m_tx_device) + FIELD(m_device_last_key_image_sync) + FIELD(m_cold_key_images) + FIELD(m_rpc_client_secret_key) + END_SERIALIZE() + /*! * \brief Check if wallet keys and bin files exist * \param file_path Wallet file path @@ -1097,6 +1234,8 @@ private: void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; } const ExportFormat & export_format() const { return m_export_format; } inline void set_export_format(const ExportFormat& export_format) { m_export_format = export_format; } + bool load_deprecated_formats() const { return m_load_deprecated_formats; } + void load_deprecated_formats(bool load) { m_load_deprecated_formats = load; } bool persistent_rpc_client_id() const { return m_persistent_rpc_client_id; } void persistent_rpc_client_id(bool persistent) { m_persistent_rpc_client_id = persistent; } void auto_mine_for_rpc_payment_threshold(float threshold) { m_auto_mine_for_rpc_payment_threshold = threshold; } @@ -1107,7 +1246,7 @@ private: void credits_target(uint64_t threshold) { m_credits_target = threshold; } bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const; - void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys); + void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const boost::optional<cryptonote::account_public_address> &single_destination_subaddress = boost::none); bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys); void check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations); void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations); @@ -1188,7 +1327,7 @@ private: * \brief Get the list of registered account tags. * \return first.Key=(tag's name), first.Value=(tag's label), second[i]=(i-th account's tag) */ - const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& get_account_tags(); + const std::pair<serializable_map<std::string, std::string>, std::vector<std::string>>& get_account_tags(); /*! * \brief Set a tag to the given accounts. * \param account_indices Indices of accounts. @@ -1528,28 +1667,28 @@ private: std::string m_mms_file; const std::unique_ptr<epee::net_utils::http::abstract_http_client> m_http_client; hashchain m_blockchain; - std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs; - std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs; - std::unordered_multimap<crypto::hash, pool_payment_details> m_unconfirmed_payments; - std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys; + serializable_unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs; + serializable_unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs; + serializable_unordered_multimap<crypto::hash, pool_payment_details> m_unconfirmed_payments; + serializable_unordered_map<crypto::hash, crypto::secret_key> m_tx_keys; cryptonote::checkpoints m_checkpoints; - std::unordered_map<crypto::hash, std::vector<crypto::secret_key>> m_additional_tx_keys; + serializable_unordered_map<crypto::hash, std::vector<crypto::secret_key>> m_additional_tx_keys; transfer_container m_transfers; payment_container m_payments; - std::unordered_map<crypto::key_image, size_t> m_key_images; - std::unordered_map<crypto::public_key, size_t> m_pub_keys; + serializable_unordered_map<crypto::key_image, size_t> m_key_images; + serializable_unordered_map<crypto::public_key, size_t> m_pub_keys; cryptonote::account_public_address m_account_public_address; - std::unordered_map<crypto::public_key, cryptonote::subaddress_index> m_subaddresses; + serializable_unordered_map<crypto::public_key, cryptonote::subaddress_index> m_subaddresses; std::vector<std::vector<std::string>> m_subaddress_labels; - std::unordered_map<crypto::hash, std::string> m_tx_notes; - std::unordered_map<std::string, std::string> m_attributes; + serializable_unordered_map<crypto::hash, std::string> m_tx_notes; + serializable_unordered_map<std::string, std::string> m_attributes; std::vector<tools::wallet2::address_book_row> m_address_book; - std::pair<std::map<std::string, std::string>, std::vector<std::string>> m_account_tags; + std::pair<serializable_map<std::string, std::string>, std::vector<std::string>> m_account_tags; uint64_t m_upper_transaction_weight_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info; const std::vector<std::vector<rct::key>> *m_multisig_rescan_k; - std::unordered_map<crypto::public_key, crypto::key_image> m_cold_key_images; + serializable_unordered_map<crypto::public_key, crypto::key_image> m_cold_key_images; std::atomic<bool> m_run; @@ -1616,7 +1755,7 @@ private: uint64_t m_credits_target; // Aux transaction data from device - std::unordered_map<crypto::hash, std::string> m_tx_device; + serializable_unordered_map<crypto::hash, std::string> m_tx_device; // Light wallet bool m_light_wallet; /* sends view key to daemon for scanning */ @@ -1630,7 +1769,7 @@ private: // We save the info from the first call in m_light_wallet_address_txs for easier lookup. std::unordered_map<crypto::hash, address_tx> m_light_wallet_address_txs; // store calculated key image for faster lookup - std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> > m_key_image_cache; + serializable_unordered_map<crypto::public_key, serializable_map<uint64_t, crypto::key_image> > m_key_image_cache; std::string m_ring_database; bool m_ring_history_saved; @@ -1657,6 +1796,7 @@ private: std::unique_ptr<wallet_device_callback> m_device_callback; ExportFormat m_export_format; + bool m_load_deprecated_formats; static boost::mutex default_daemon_address_lock; static std::string default_daemon_address; @@ -2053,7 +2193,7 @@ namespace boost a & x.key_images; if (ver < 1) return; - a & x.tx_key_images; + a & x.tx_key_images.parent(); } template <class Archive> diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 2391b51fd..0ed749cb7 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -838,10 +838,11 @@ namespace tools static std::string ptx_to_string(const tools::wallet2::pending_tx &ptx) { std::ostringstream oss; - boost::archive::portable_binary_oarchive ar(oss); + binary_archive<true> ar(oss); try { - ar << ptx; + if (!::serialization::serialize(ar, const_cast<tools::wallet2::pending_tx&>(ptx))) + return ""; } catch (...) { @@ -1550,14 +1551,31 @@ namespace tools return false; } + bool loaded = false; tools::wallet2::pending_tx ptx; + try { std::istringstream iss(blob); - boost::archive::portable_binary_iarchive ar(iss); - ar >> ptx; + binary_archive<false> ar(iss); + if (::serialization::serialize(ar, ptx)) + loaded = true; } - catch (...) + catch(...) {} + + if (!loaded && !m_restricted) + { + try + { + std::istringstream iss(blob); + boost::archive::portable_binary_iarchive ar(iss); + ar >> ptx; + loaded = true; + } + catch (...) {} + } + + if (!loaded) { er.code = WALLET_RPC_ERROR_CODE_BAD_TX_METADATA; er.message = "Failed to parse tx metadata."; diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index ae861d177..5b2536bf1 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 18 +#define WALLET_RPC_VERSION_MINOR 19 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index 10b1b9af4..fb8ddbe11 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -655,3 +655,19 @@ bool gen_block_late_v1_coinbase_tx::generate(std::vector<test_event_entry>& even return true; } + +bool gen_block_low_coinbase::generate(std::vector<test_event_entry>& events) const +{ + BLOCK_VALIDATION_INIT_GENERATE(); + + block blk_1; + std::vector<size_t> block_weights; + generator.construct_block(blk_1, cryptonote::get_block_height(blk_0) + 1, cryptonote::get_block_hash(blk_0), + miner_account, blk_0.timestamp + DIFFICULTY_TARGET_V2, COIN + generator.get_already_generated_coins(cryptonote::get_block_hash(blk_0)), + block_weights, {}, HF_VERSION_EXACT_COINBASE); + events.push_back(blk_1); + + DO_CALLBACK(events, "check_block_purged"); + + return true; +} diff --git a/tests/core_tests/block_validation.h b/tests/core_tests/block_validation.h index 39eba0829..0dd4e145c 100644 --- a/tests/core_tests/block_validation.h +++ b/tests/core_tests/block_validation.h @@ -218,3 +218,15 @@ struct get_test_options<gen_block_late_v1_coinbase_tx> { hard_forks, 0 }; }; + +struct gen_block_low_coinbase : public gen_block_verification_base<1> +{ + bool generate(std::vector<test_event_entry>& events) const; +}; +template<> +struct get_test_options<gen_block_low_coinbase> { + const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(HF_VERSION_EXACT_COINBASE, 1), std::make_pair(0, 0)}; + const cryptonote::test_options test_options = { + hard_forks, 0 + }; +}; diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index edaa9b20a..8b6135510 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -35,8 +35,6 @@ #include <iostream> #include <stdint.h> -#include <boost/archive/binary_oarchive.hpp> -#include <boost/archive/binary_iarchive.hpp> #include <boost/program_options.hpp> #include <boost/optional.hpp> #include <boost/serialization/vector.hpp> diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 38382b95f..9895d4814 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -264,6 +264,8 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_bp_tx_invalid_wrong_amount); GENERATE_AND_PLAY(gen_bp_tx_invalid_borromean_type); + GENERATE_AND_PLAY(gen_block_low_coinbase); + el::Level level = (failed_tests.empty() ? el::Level::Info : el::Level::Error); if (!list_tests) { diff --git a/tests/data/fuzz/cold-outputs/OUTPUTS1 b/tests/data/fuzz/cold-outputs/OUTPUTS1 Binary files differdeleted file mode 100644 index f449f61ad..000000000 --- a/tests/data/fuzz/cold-outputs/OUTPUTS1 +++ /dev/null diff --git a/tests/data/fuzz/cold-outputs/OUTPUTS2 b/tests/data/fuzz/cold-outputs/OUTPUTS2 Binary files differdeleted file mode 100644 index 33cf39024..000000000 --- a/tests/data/fuzz/cold-outputs/OUTPUTS2 +++ /dev/null diff --git a/tests/data/fuzz/cold-outputs/out-all-6 b/tests/data/fuzz/cold-outputs/out-all-6 Binary files differnew file mode 100644 index 000000000..d24fc604f --- /dev/null +++ b/tests/data/fuzz/cold-outputs/out-all-6 diff --git a/tests/data/fuzz/cold-outputs/out-none-6 b/tests/data/fuzz/cold-outputs/out-none-6 Binary files differnew file mode 100644 index 000000000..c5390590c --- /dev/null +++ b/tests/data/fuzz/cold-outputs/out-none-6 diff --git a/tests/data/fuzz/cold-transaction/CTX1 b/tests/data/fuzz/cold-transaction/CTX1 Binary files differindex 0afecedbc..4b9ee45dc 100644 --- a/tests/data/fuzz/cold-transaction/CTX1 +++ b/tests/data/fuzz/cold-transaction/CTX1 diff --git a/tests/functional_tests/functional_tests_rpc.py b/tests/functional_tests/functional_tests_rpc.py index 5f2a3d077..3be62c0ca 100755 --- a/tests/functional_tests/functional_tests_rpc.py +++ b/tests/functional_tests/functional_tests_rpc.py @@ -10,7 +10,7 @@ import string import os USAGE = 'usage: functional_tests_rpc.py <python> <srcdir> <builddir> [<tests-to-run> | all]' -DEFAULT_TESTS = ['address_book', 'bans', 'blockchain', 'cold_signing', 'daemon_info', 'get_output_distribution', 'integrated_address', 'mining', 'multisig', 'proofs', 'rpc_payment', 'sign_message', 'transfer', 'txpool', 'uri', 'validate_address', 'wallet'] +DEFAULT_TESTS = ['address_book', 'bans', 'blockchain', 'cold_signing', 'daemon_info', 'get_output_distribution', 'integrated_address', 'mining', 'multisig', 'p2p', 'proofs', 'rpc_payment', 'sign_message', 'transfer', 'txpool', 'uri', 'validate_address', 'wallet'] try: python = sys.argv[1] srcdir = sys.argv[2] @@ -34,18 +34,32 @@ try: except: tests = DEFAULT_TESTS -N_MONERODS = 2 -N_WALLETS = 4 +# a main offline monerod, does most of the tests +# a restricted RPC monerod setup with RPC payment +# two local online monerods connected to each other +N_MONERODS = 4 + +# 4 wallets connected to the main offline monerod +# a wallet connected to the first local online monerod +N_WALLETS = 5 + WALLET_DIRECTORY = builddir + "/functional-tests-directory" DIFFICULTY = 10 -monerod_base = [builddir + "/bin/monerod", "--regtest", "--fixed-difficulty", str(DIFFICULTY), "--offline", "--no-igd", "--p2p-bind-port", "monerod_p2p_port", "--rpc-bind-port", "monerod_rpc_port", "--zmq-rpc-bind-port", "monerod_zmq_port", "--non-interactive", "--disable-dns-checkpoints", "--check-updates", "disabled", "--rpc-ssl", "disabled", "--log-level", "1"] +monerod_base = [builddir + "/bin/monerod", "--regtest", "--fixed-difficulty", str(DIFFICULTY), "--no-igd", "--p2p-bind-port", "monerod_p2p_port", "--rpc-bind-port", "monerod_rpc_port", "--zmq-rpc-bind-port", "monerod_zmq_port", "--non-interactive", "--disable-dns-checkpoints", "--check-updates", "disabled", "--rpc-ssl", "disabled", "--data-dir", "monerod_data_dir", "--log-level", "1"] monerod_extra = [ - [], - ["--rpc-payment-address", "44SKxxLQw929wRF6BA9paQ1EWFshNnKhXM3qz6Mo3JGDE2YG3xyzVutMStEicxbQGRfrYvAAYxH6Fe8rnD56EaNwUiqhcwR", "--rpc-payment-difficulty", str(DIFFICULTY), "--rpc-payment-credits", "5000", "--data-dir", builddir + "/functional-tests-directory/monerod1"], + ["--offline"], + ["--rpc-payment-address", "44SKxxLQw929wRF6BA9paQ1EWFshNnKhXM3qz6Mo3JGDE2YG3xyzVutMStEicxbQGRfrYvAAYxH6Fe8rnD56EaNwUiqhcwR", "--rpc-payment-difficulty", str(DIFFICULTY), "--rpc-payment-credits", "5000", "--offline"], + ["--add-exclusive-node", "127.0.0.1:18283"], + ["--add-exclusive-node", "127.0.0.1:18282"], ] -wallet_base = [builddir + "/bin/monero-wallet-rpc", "--wallet-dir", WALLET_DIRECTORY, "--rpc-bind-port", "wallet_port", "--disable-rpc-login", "--rpc-ssl", "disabled", "--daemon-ssl", "disabled", "--daemon-port", "18180", "--log-level", "1"] +wallet_base = [builddir + "/bin/monero-wallet-rpc", "--wallet-dir", WALLET_DIRECTORY, "--rpc-bind-port", "wallet_port", "--disable-rpc-login", "--rpc-ssl", "disabled", "--daemon-ssl", "disabled", "--log-level", "1"] wallet_extra = [ + ["--daemon-port", "18180"], + ["--daemon-port", "18180"], + ["--daemon-port", "18180"], + ["--daemon-port", "18180"], + ["--daemon-port", "18182"], ] command_lines = [] @@ -54,7 +68,7 @@ outputs = [] ports = [] for i in range(N_MONERODS): - command_lines.append([str(18180+i) if x == "monerod_rpc_port" else str(18280+i) if x == "monerod_p2p_port" else str(18380+i) if x == "monerod_zmq_port" else x for x in monerod_base]) + command_lines.append([str(18180+i) if x == "monerod_rpc_port" else str(18280+i) if x == "monerod_p2p_port" else str(18380+i) if x == "monerod_zmq_port" else builddir + "/functional-tests-directory/monerod" + str(i) if x == "monerod_data_dir" else x for x in monerod_base]) if i < len(monerod_extra): command_lines[-1] += monerod_extra[i] outputs.append(open(builddir + '/tests/functional_tests/monerod' + str(i) + '.log', 'a+')) @@ -109,6 +123,9 @@ if not all_open: kill() sys.exit(1) +# online daemons need some time to connect to peers to be ready +time.sleep(2) + PASS = [] FAIL = [] for test in tests: diff --git a/tests/functional_tests/p2p.py b/tests/functional_tests/p2p.py new file mode 100755 index 000000000..f36e9c0b1 --- /dev/null +++ b/tests/functional_tests/p2p.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2018 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. + +from __future__ import print_function +import time + +"""Test daemon P2P +""" + +from framework.daemon import Daemon +from framework.wallet import Wallet + +class P2PTest(): + def run_test(self): + self.reset() + self.create() + self.mine(80) + self.test_p2p_reorg() + self.test_p2p_tx_propagation() + + def reset(self): + print('Resetting blockchain') + daemon = Daemon() + res = daemon.get_height() + daemon.pop_blocks(res.height - 1) + daemon.flush_txpool() + + def create(self): + print('Creating wallet') + seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted' + self.wallet = Wallet(idx = 4) + # close the wallet if any, will throw if none is loaded + try: self.wallet.close_wallet() + except: pass + res = self.wallet.restore_deterministic_wallet(seed = seed) + + def mine(self, blocks): + assert blocks >= 1 + + print("Generating", blocks, 'blocks') + + daemon = Daemon(idx = 2) + + # generate blocks + res_generateblocks = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', blocks) + + def test_p2p_reorg(self): + print('Testing P2P reorg') + daemon2 = Daemon(idx = 2) + daemon3 = Daemon(idx = 3) + + # give sync some time + time.sleep(1) + + res = daemon2.get_info() + height = res.height + assert height > 0 + top_block_hash = res.top_block_hash + assert len(top_block_hash) == 64 + + res = daemon3.get_info() + assert res.height == height + assert res.top_block_hash == top_block_hash + + # disconnect daemons and mine separately on both + daemon2.out_peers(0) + daemon3.out_peers(0) + + res = daemon2.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 2) + res = daemon3.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 3) + + res = daemon2.get_info() + assert res.height == height + 2 + daemon2_top_block_hash = res.top_block_hash + assert daemon2_top_block_hash != top_block_hash + res = daemon3.get_info() + assert res.height == height + 3 + daemon3_top_block_hash = res.top_block_hash + assert daemon3_top_block_hash != top_block_hash + assert daemon3_top_block_hash != daemon2_top_block_hash + + # reconnect, daemon2 will now switch to daemon3's chain + daemon2.out_peers(8) + daemon3.out_peers(8) + time.sleep(10) + res = daemon2.get_info() + assert res.height == height + 3 + assert res.top_block_hash == daemon3_top_block_hash + + # disconect, mine on daemon2 again more than daemon3 + daemon2.out_peers(0) + daemon3.out_peers(0) + + res = daemon2.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 3) + res = daemon3.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 2) + + res = daemon2.get_info() + assert res.height == height + 6 + daemon2_top_block_hash = res.top_block_hash + assert daemon2_top_block_hash != top_block_hash + res = daemon3.get_info() + assert res.height == height + 5 + daemon3_top_block_hash = res.top_block_hash + assert daemon3_top_block_hash != top_block_hash + assert daemon3_top_block_hash != daemon2_top_block_hash + + # reconnect, daemon3 will now switch to daemon2's chain + daemon2.out_peers(8) + daemon3.out_peers(8) + time.sleep(5) + res = daemon3.get_info() + assert res.height == height + 6 + assert res.top_block_hash == daemon2_top_block_hash + + def test_p2p_tx_propagation(self): + print('Testing P2P tx propagation') + daemon2 = Daemon(idx = 2) + daemon3 = Daemon(idx = 3) + + for daemon in [daemon2, daemon3]: + res = daemon.get_transaction_pool_hashes() + assert not 'tx_hashes' in res or len(res.tx_hashes) == 0 + + self.wallet.refresh() + res = self.wallet.get_balance() + + dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} + res = self.wallet.transfer([dst]) + assert len(res.tx_hash) == 32*2 + txid = res.tx_hash + + time.sleep(5) + + for daemon in [daemon2, daemon3]: + res = daemon.get_transaction_pool_hashes() + assert len(res.tx_hashes) == 1 + assert res.tx_hashes[0] == txid + + +if __name__ == '__main__': + P2PTest().run_test() diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp index 797a369a5..2698a36ba 100644 --- a/tests/fuzz/cold-outputs.cpp +++ b/tests/fuzz/cold-outputs.cpp @@ -40,7 +40,7 @@ BEGIN_INIT_SIMPLE_FUZZER() static tools::wallet2 local_wallet; wallet = &local_wallet; - static const char * const spendkey_hex = "0b4f47697ec99c3de6579304e5f25c68b07afbe55b71d99620bf6cbf4e45a80f"; + static const char * const spendkey_hex = "f285d4ac9e66271256fc7cde0d3d6b36f66efff6ccd766706c408e86f4997a0d"; crypto::secret_key spendkey; epee::string_tools::hex_to_pod(spendkey_hex, spendkey); @@ -50,12 +50,12 @@ BEGIN_INIT_SIMPLE_FUZZER() END_INIT_SIMPLE_FUZZER() BEGIN_SIMPLE_FUZZER() - std::string s = std::string("\x01\x16serialization::archive") + std::string((const char*)buf, len); + std::string s((const char*)buf, len); std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs; std::stringstream iss; iss << s; - boost::archive::portable_binary_iarchive ar(iss); - ar >> outputs; + binary_archive<false> ar(iss); + ::serialization::serialize(ar, outputs); size_t n_outputs = wallet->import_outputs(outputs); std::cout << boost::lexical_cast<std::string>(n_outputs) << " outputs imported" << std::endl; END_SIMPLE_FUZZER() diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp index 36fb35e15..135343704 100644 --- a/tests/fuzz/cold-transaction.cpp +++ b/tests/fuzz/cold-transaction.cpp @@ -40,7 +40,7 @@ BEGIN_INIT_SIMPLE_FUZZER() static tools::wallet2 local_wallet; wallet = &local_wallet; - static const char * const spendkey_hex = "0b4f47697ec99c3de6579304e5f25c68b07afbe55b71d99620bf6cbf4e45a80f"; + static const char * const spendkey_hex = "f285d4ac9e66271256fc7cde0d3d6b36f66efff6ccd766706c408e86f4997a0d"; crypto::secret_key spendkey; epee::string_tools::hex_to_pod(spendkey_hex, spendkey); @@ -50,12 +50,12 @@ BEGIN_INIT_SIMPLE_FUZZER() END_INIT_SIMPLE_FUZZER() BEGIN_SIMPLE_FUZZER() - std::string s = std::string("\x01\x16serialization::archive") + std::string((const char*)buf, len); + std::string s((const char*)buf, len); tools::wallet2::unsigned_tx_set exported_txs; std::stringstream iss; iss << s; - boost::archive::portable_binary_iarchive ar(iss); - ar >> exported_txs; + binary_archive<false> ar(iss); + ::serialization::serialize(ar, exported_txs); std::vector<tools::wallet2::pending_tx> ptx; bool success = wallet->sign_tx(exported_txs, "/tmp/cold-transaction-test-signed", ptx); std::cout << (success ? "signed" : "error") << std::endl; diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index ee205e666..e730f6867 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -42,7 +42,7 @@ #include "serialization/json_archive.h" #include "serialization/debug_archive.h" #include "serialization/variant.h" -#include "serialization/vector.h" +#include "serialization/containers.h" #include "serialization/binary_utils.h" #include "wallet/wallet2.h" #include "gtest/gtest.h" diff --git a/tests/unit_tests/varint.cpp b/tests/unit_tests/varint.cpp index ca5af5ad2..a8dee677a 100644 --- a/tests/unit_tests/varint.cpp +++ b/tests/unit_tests/varint.cpp @@ -40,7 +40,7 @@ #include "serialization/json_archive.h" #include "serialization/debug_archive.h" #include "serialization/variant.h" -#include "serialization/vector.h" +#include "serialization/containers.h" #include "serialization/binary_utils.h" #include "gtest/gtest.h" using namespace std; |