From a3834f937c02ef536cf33a8d24058ce98458306a Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Thu, 24 Sep 2015 11:00:46 -0400 Subject: [PATCH 01/11] Updated documentation for blockchain.* All functions are now documented in doxygen format. Comments have been updated to reflect the current state of the code. Many areas for improvement in clarity and design have been noted, as well as cruft to be removed. These changes are not reflected in this commit both to allow time for comment and to keep commits organized by purpose. --- src/cryptonote_core/blockchain.cpp | 43 +- src/cryptonote_core/blockchain.h | 841 ++++++++++++++++++++++++++++- 2 files changed, 853 insertions(+), 31 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 5620466fc..597869e16 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -310,6 +310,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet) // we only need 1 m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service)); + //TODO: move this block into separate functions? #if defined(PER_BLOCK_CHECKPOINT) if (m_fast_sync && !testnet && get_blocks_dat_start() != nullptr) { @@ -803,7 +804,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list blocks, starting at -// and return by reference . +// get the block sizes of the last blocks, and return by reference . void Blockchain::get_last_n_blocks_sizes(std::vector& sz, size_t count) const { LOG_PRINT_L3("Blockchain::" << __func__); @@ -1351,6 +1351,10 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list missed_tx_id; std::list txs; + + // FIXME: s/rsp.missed_ids/missed_tx_id/ ? Seems like rsp.missed_ids + // is for missed blocks, not missed transactions as well. get_transactions(bl.tx_hashes, txs, rsp.missed_ids); CHECK_AND_ASSERT_MES(!missed_tx_id.size(), false, "Internal error: has missed missed_tx_id.size()=" << missed_tx_id.size() << std::endl << "for block id = " << get_block_hash(bl)); @@ -1581,6 +1588,8 @@ uint64_t Blockchain::block_difficulty(uint64_t i) const return 0; } //------------------------------------------------------------------ +//TODO: return type should be void, throw on exception +// alternatively, return true only if no blocks missed template bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const { @@ -1605,6 +1614,8 @@ bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container return true; } //------------------------------------------------------------------ +//TODO: return type should be void, throw on exception +// alternatively, return true only if no transactions missed template bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const { @@ -1621,7 +1632,6 @@ bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container { missed_txs.push_back(tx_hash); } - //FIXME: is this the correct way to handle this? catch (const std::exception& e) { return false; @@ -1878,6 +1888,11 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vectorheight() < m_blocks_hash_check.size() && kept_by_block) { TIME_MEASURE_START(a); @@ -1936,6 +1952,10 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const // This function validates transaction inputs and their keys. Previously // it also performed double spend checking, but that has been moved to its // own function. +// FIXME: consider moving functionality specific to one input into +// check_tx_input() rather than here, and use this function simply +// to iterate the inputs as necessary (splitting the task +// using threads, etc.) bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_block_height) { LOG_PRINT_L3("Blockchain::" << __func__); @@ -2143,6 +2163,9 @@ bool Blockchain::check_tx_input(const txin_to_key& txin, const crypto::hash& tx_ // 1. Disable locking and make method private. //CRITICAL_REGION_LOCAL(m_blockchain_lock); + //FIXME: this doesn't appear to be a good use of the visitor pattern, + // but rather more complicated than necessary. I may be wrong + // though - TW struct outputs_visitor { std::vector& m_output_keys; @@ -2167,7 +2190,7 @@ bool Blockchain::check_tx_input(const txin_to_key& txin, const crypto::hash& tx_ output_keys.clear(); - //check ring signature + // collect output keys outputs_visitor vi(output_keys, *this); if (!scan_outputkeys_for_indexes(txin, vi, tx_prefix_hash, pmax_related_block_height)) { @@ -2414,6 +2437,11 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& txs.push_back(tx); TIME_MEASURE_START(dd); + // FIXME: the storage should not be responsible for validation. + // If it does any, it is merely a sanity check. + // Validation is the purview of the Blockchain class + // - TW + // // ND: this is not needed, db->add_block() checks for duplicate k_images and fails accordingly. // if (!check_for_double_spend(tx, keys)) // { @@ -2589,6 +2617,8 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc return handle_block_to_main_chain(bl, id, bvc); } //------------------------------------------------------------------ +//TODO: Refactor, consider returning a failure height and letting +// caller decide course of action. void Blockchain::check_against_checkpoints(const checkpoints& points, bool enforce) { const auto& pts = points.get_points(); @@ -2667,6 +2697,8 @@ void Blockchain::block_longhash_worker(const uint64_t height, const std::vector< TIME_MEASURE_START(t); slow_hash_allocate_state(); + //FIXME: height should be changing here, as get_block_longhash expects + // the height of the block passed to it for (const auto & block : blocks) { crypto::hash id = get_block_hash(block); @@ -2722,6 +2754,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) } //------------------------------------------------------------------ +//FIXME: unused parameter txs void Blockchain::output_scan_worker(const uint64_t amount, const std::vector &offsets, std::vector &outputs, std::unordered_map &txs) const { try diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 57763f6ca..6f44c0482 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -56,11 +56,14 @@ namespace cryptonote { class tx_memory_pool; + /** Declares ways in which the BlockchainDB backend should be told to sync + * + */ enum blockchain_db_sync_mode { - db_sync, - db_async, - db_nosync + db_sync, //!< handle syncing calls instead of the backing db, synchronously + db_async, //!< handle syncing calls instead of the backing db, asynchronously + db_nosync //!< Leave syncing up to the backing db (safest, but slowest because of disk I/O) }; /************************************************************************/ @@ -69,6 +72,9 @@ namespace cryptonote class Blockchain { public: + /** + * @brief Now-defunct (TODO: remove) struct from in-memory blockchain + */ struct transaction_chain_entry { transaction tx; @@ -77,116 +83,598 @@ namespace cryptonote std::vector m_global_output_indexes; }; + /** + * @brief container for passing a block and metadata about it on the blockchain + */ struct block_extended_info { - block bl; - uint64_t height; - size_t block_cumulative_size; - difficulty_type cumulative_difficulty; - uint64_t already_generated_coins; + block bl; //!< the block + uint64_t height; //!< the height of the block in the blockchain + size_t block_cumulative_size; //!< the size (in bytes) of the block + difficulty_type cumulative_difficulty; //!< the accumulated difficulty after that block + uint64_t already_generated_coins; //!< the total coins minted after that block }; + /** + * @brief Blockchain constructor + * + * @param tx_pool a reference to the transaction pool to be kept by the Blockchain + */ Blockchain(tx_memory_pool& tx_pool); + /** + * @brief Initialize the Blockchain state + * + * @param db a pointer to the backing store to use for the blockchain + * @param testnet true if on testnet, else false + * + * @return true on success, false if any initialization steps fail + */ bool init(BlockchainDB* db, const bool testnet = false); + + /** + * @brief Uninitializes the blockchain state + * + * Saves to disk any state that needs to be maintained + * + * @return true on success, false if any uninitialization steps fail + */ bool deinit(); + /** + * @brief assign a set of blockchain checkpoint hashes + * + * @param chk_pts the set of checkpoints to assign + */ void set_checkpoints(checkpoints&& chk_pts) { m_checkpoints = chk_pts; } - //bool push_new_block(); + /** + * @brief get blocks and transactions from blocks based on start height and count + * + * @param start_offset the height on the blockchain to start at + * @param count the number of blocks to get, if there are as many after start_offset + * @param blocks return-by-reference container to put result blocks in + * @param txs return-by-reference container to put result transactions in + * + * @return false if start_offset > blockchain height, else true + */ bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs) const; + + /** + * @brief get blocks from blocks based on start height and count + * + * @param start_offset the height on the blockchain to start at + * @param count the number of blocks to get, if there are as many after start_offset + * @param blocks return-by-reference container to put result blocks in + * + * @return false if start_offset > blockchain height, else true + */ bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks) const; + + /** + * @brief compiles a list of all blocks stored as alternative chains + * + * @param blocks return-by-reference container to put result blocks in + * + * @return true + */ bool get_alternative_blocks(std::list& blocks) const; + + /** + * @brief returns the number of alternative blocks stored + * + * @return the number of alternative blocks stored + */ size_t get_alternative_blocks_count() const; + + /** + * @brief gets a block's hash given a height + * + * @param height the height of the block + * + * @return the hash of the block at the requested height, or a zeroed hash if there is no such block + */ crypto::hash get_block_id_by_height(uint64_t height) const; + + /** + * @brief gets the block with a given hash + * + * @param h the hash to look for + * @param blk return-by-reference variable to put result block in + * + * @return true if the block was found, else false + */ bool get_block_by_hash(const crypto::hash &h, block &blk) const; + + /** + * @brief get all block hashes (main chain, alt chains, and invalid blocks) + * + * @param main return-by-reference container to put result main chain blocks' hashes in + * @param alt return-by-reference container to put result alt chain blocks' hashes in + * @param invalid return-by-reference container to put result invalid blocks' hashes in + */ void get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid) const; + + /** + * @brief performs some preprocessing on a group of incoming blocks to speed up verification + * + * @param blocks a list of incoming blocks + * + * @return false on erroneous blocks, else true + */ bool prepare_handle_incoming_blocks(const std::list &blocks); + + /** + * @brief incoming blocks post-processing, cleanup, and disk sync + * + * @param force_sync if true, and Blockchain is handling syncing to disk, always sync + * + * @return true + */ bool cleanup_handle_incoming_blocks(bool force_sync = false); + /** + * @brief old serialization to disk, pending removal + * + * @tparam archive_t + * @param ar + * @param version + */ template void serialize(archive_t & ar, const unsigned int version); + /** + * @brief search the blockchain for a transaction by hash + * + * @param id the hash to search for + * + * @return true if the tx exists, else false + */ bool have_tx(const crypto::hash &id) const; + + /** + * @brief check if any key image in a transaction has already been spent + * + * @param tx the transaction to check + * + * @return true if any key image is already spent in the blockchain, else false + */ bool have_tx_keyimges_as_spent(const transaction &tx) const; + + /** + * @brief check if a key image is already spent on the blockchain + * + * Whenever a transaction output is used as an input for another transaction + * (a true input, not just one of a mixing set), a key image is generated + * and stored in the transaction in order to prevent double spending. If + * this key image is seen again, the transaction using it is rejected. + * + * @param key_im the key image to search for + * + * @return true if the key image is already spent in the blockchain, else false + */ bool have_tx_keyimg_as_spent(const crypto::key_image &key_im) const; + /** + * @brief get the current height of the blockchain + * + * @return the height + */ uint64_t get_current_blockchain_height() const; + + /** + * @brief get the hash of the most recent block on the blockchain + * + * @return the hash + */ crypto::hash get_tail_id() const; + + /** + * @brief get the height and hash of the most recent block on the blockchain + * + * @param height return-by-reference variable to store the height in + * + * @return the hash + */ crypto::hash get_tail_id(uint64_t& height) const; + + /** + * @brief returns the difficulty target the next block to be added must meet + * + * @return the target + */ difficulty_type get_difficulty_for_next_block(); + + /** + * @brief adds a block to the blockchain + * + * Adds a new block to the blockchain. If the block's parent is not the + * current top of the blockchain, the block may be added to an alternate + * chain. If the block does not belong, is already in the blockchain + * or an alternate chain, or is invalid, return false. + * + * @param bl_ the block to be added + * @param bvc metadata about the block addition's success/failure + * + * @return true on successful addition to the blockchain, else false + */ bool add_new_block(const block& bl_, block_verification_context& bvc); + + /** + * @brief clears the blockchain and starts a new one + * + * @param b the first block in the new chain (the genesis block) + * + * @return true on success, else false + */ bool reset_and_set_genesis_block(const block& b); + + /** + * @brief creates a new block to mine against + * + * @param b return-by-reference block to be filled in + * @param miner_address address new coins for the block will go to + * @param di return-by-reference tells the miner what the difficulty target is + * @param height return-by-reference tells the miner what height it's mining against + * @param ex_nonce extra data to be added to the miner transaction's extra + * + * @return true if block template filled in successfully, else false + */ bool create_block_template(block& b, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, const blobdata& ex_nonce); + + /** + * @brief checks if a block is known about with a given hash + * + * This function checks the main chain, alternate chains, and invalid blocks + * for a block with the given hash + * + * @param id the hash to search for + * + * @return true if the block is known, else false + */ bool have_block(const crypto::hash& id) const; + + /** + * @brief gets the total number of transactions on the main chain + * + * @return the number of transactions on the main chain + */ size_t get_total_transactions() const; + + /** + * @brief gets the hashes for a subset of the blockchain + * + * puts into list a list of hashes representing certain blocks + * from the blockchain in reverse chronological order + * + * the blocks chosen, at the time of this writing, are: + * the most recent 11 + * powers of 2 less recent from there, so 13, 17, 25, etc... + * + * @param ids return-by-reference list to put the resulting hashes in + * + * @return true + */ bool get_short_chain_history(std::list& ids) const; + + /** + * @brief get recent block hashes for a foreign chain + * + * Find the split point between us and foreign blockchain and return + * (by reference) the most recent common block hash along with up to + * BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes. + * + * @param qblock_ids the foreign chain's "short history" (see get_short_chain_history) + * @param resp return-by-reference the split height and subsequent blocks' hashes + * + * @return true if a block found in common, else false + */ bool find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const; + + /** + * @brief find the most recent common point between ours and a foreign chain + * + * This function takes a list of block hashes from another node + * on the network to find where the split point is between us and them. + * This is used to see what to send another node that needs to sync. + * + * @param qblock_ids the foreign chain's "short history" (see get_short_chain_history) + * @param starter_offset return-by-reference the most recent common block's height + * + * @return true if a block found in common, else false + */ bool find_blockchain_supplement(const std::list& qblock_ids, uint64_t& starter_offset) const; + + /** + * @brief get recent blocks for a foreign chain + * + * This function gets recent blocks relative to a foreign chain, starting either at + * a requested height or whatever height is the most recent ours and the foreign + * chain have in common. + * + * @param req_start_block if non-zero, specifies a start point (otherwise find most recent commonality) + * @param qblock_ids the foreign chain's "short history" (see get_short_chain_history) + * @param blocks return-by-reference the blocks and their transactions + * @param total_height return-by-reference our current blockchain height + * @param start_height return-by-reference the height of the first block returned + * @param max_count the max number of blocks to get + * + * @return true if a block found in common or req_start_block specified, else false + */ bool find_blockchain_supplement(const uint64_t req_start_block, const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const; + + /** + * @brief retrieves a set of blocks and their transactions, and possibly other transactions + * + * the request object encapsulates a list of block hashes and a (possibly empty) list of + * transaction hashes. for each block hash, the block is fetched along with all of that + * block's transactions. Any transactions requested separately are fetched afterwards. + * + * @param arg the request + * @param rsp return-by-reference the response to fill in + * + * @return true unless any blocks or transactions are missing + */ bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp); + + //FIXME: function declared, but never defined or used. Candidate for removal. bool handle_get_objects(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res); + + /** + * @brief gets random outputs to mix with + * + * This function takes an RPC request for outputs to mix with + * and creates an RPC response with the resultant output indices. + * + * Outputs to mix with are randomly selected from the utxo set + * for each output amount in the request. + * + * @param req the output amounts and number of mixins to select + * @param res return-by-reference the resultant output indices + * + * @return true + */ bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const; + + /** + * @brief gets the global indices for outputs from a given transaction + * + * This function gets the global indices for all outputs belonging + * to a specific transaction. + * + * @param tx_id the hash of the transaction to fetch indices for + * @param indexs return-by-reference the global indices for the transaction's outputs + * + * @return false if the transaction does not exist, or if no indices are found, otherwise true + */ bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs) const; + + /** + * @brief stores the blockchain + * + * If Blockchain is handling storing of the blockchain (rather than BlockchainDB), + * this initiates a blockchain save. + * + * @return true unless saving the blockchain fails + */ bool store_blockchain(); + /** + * @brief validates a transaction's inputs + * + * validates a transaction's inputs as correctly used and not previously + * spent. also returns the hash and height of the most recent block + * which contains an output that was used as an input to the transaction. + * + * @param tx the transaction to validate + * @param pmax_used_block_height return-by-reference block height of most recent input + * @param max_used_block_id return-by-reference block hash of most recent input + * @param kept_by_block whether or not the transaction is from a previously-verified block + * + * @return false if any input is invalid, otherwise true + */ bool check_tx_inputs(const transaction& tx, uint64_t& pmax_used_block_height, crypto::hash& max_used_block_id, bool kept_by_block = false); + + /** + * @brief gets the blocksize limit based on recent blocks + * + * @return the limit + */ uint64_t get_current_cumulative_blocksize_limit() const; + + /** + * @brief checks if the blockchain is currently being stored + * + * Note: this should be meaningless in cases where Blockchain is not + * directly managing saving the blockchain to disk. + * + * @return true if Blockchain is having the chain stored currently, else false + */ bool is_storing_blockchain()const{return m_is_blockchain_storing;} + + /** + * @brief gets the difficulty of the block with a given height + * + * @param i the height + * + * @return the difficulty + */ uint64_t block_difficulty(uint64_t i) const; + /** + * @brief gets blocks based on a list of block hashes + * + * @tparam t_ids_container a standard-iterable container + * @tparam t_blocks_container a standard-iterable container + * @tparam t_missed_container a standard-iterable container + * @param block_ids a container of block hashes for which to get the corresponding blocks + * @param blocks return-by-reference a container to store result blocks in + * @param missed_bs return-by-reference a container to store missed blocks in + * + * @return false if an unexpected exception occurs, else true + */ template bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const; + /** + * @brief gets transactions based on a list of transaction hashes + * + * @tparam t_ids_container a standard-iterable container + * @tparam t_tx_container a standard-iterable container + * @tparam t_missed_container a standard-iterable container + * @param txs_ids a container of hashes for which to get the corresponding transactions + * @param txs return-by-reference a container to store result transactions in + * @param missed_txs return-by-reference a container to store missed transactions in + * + * @return false if an unexpected exception occurs, else true + */ template bool get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const; + //debug functions + + /** + * @brief prints data about a snippet of the blockchain + * + * if start_index is greater than the blockchain height, do nothing + * + * @param start_index height on chain to start at + * @param end_index height on chain to end at + */ void print_blockchain(uint64_t start_index, uint64_t end_index); + + /** + * @brief prints every block's hash + * + * WARNING: This function will absolutely crush a terminal in prints, so + * it is recommended to redirect this output to a log file (or null sink + * if a log file is already set up, as should be the default) + */ void print_blockchain_index(); + + /** + * @brief currently does nothing, candidate for removal + * + * @param file + */ void print_blockchain_outs(const std::string& file); + /** + * @brief check the blockchain against a set of checkpoints + * + * If a block fails a checkpoint and enforce is enabled, the blockchain + * will be rolled back to two blocks prior to that block. If enforce + * is disabled, as is currently the default case with DNS-based checkpoints, + * an error will be printed to the user but no other action will be taken. + * + * @param points the checkpoints to check against + * @param enforce whether or not to take action on failure + */ void check_against_checkpoints(const checkpoints& points, bool enforce); + + /** + * @brief configure whether or not to enforce DNS-based checkpoints + * + * @param enforce the new enforcement setting + */ void set_enforce_dns_checkpoints(bool enforce); + + /** + * @brief loads new checkpoints from a file and optionally from DNS + * + * @param file_path the path of the file to look for and load checkpoints from + * @param check_dns whether or not to check for new DNS-based checkpoints + * + * @return false if any enforced checkpoint type fails to load, otherwise true + */ bool update_checkpoints(const std::string& file_path, bool check_dns); + // user options, must be called before calling init() + + //FIXME: parameter names don't match function definition in .cpp file + /** + * @brief sets various performance options + * + * @param block_threads max number of threads when preparing blocks for addition + * @param blocks_per_sync number of blocks to cache before syncing to database + * @param sync_mode the ::blockchain_db_sync_mode to use + * @param fast_sync sync using built-in block hashes as trusted + */ void set_user_options(uint64_t block_threads, uint64_t blocks_per_sync, blockchain_db_sync_mode sync_mode, bool fast_sync); + /** + * @brief set whether or not to show/print time statistics + * + * @param stats the new time stats setting + */ void set_show_time_stats(bool stats) { m_show_time_stats = stats; } + /** + * @brief get a reference to the BlockchainDB in use by Blockchain + * + * @return a reference to the BlockchainDB instance + */ BlockchainDB& get_db() { return *m_db; } - void output_scan_worker(const uint64_t amount,const std::vector &offsets, - std::vector &outputs, std::unordered_map &txs) const; + /** + * @brief get a number of outputs of a specific amount + * + * @param amount the amount + * @param offsets the indices (indexed to the amount) of the outputs + * @param outputs return-by-reference the outputs collected + * @param txs unused, candidate for removal + */ + void output_scan_worker(const uint64_t amount,const std::vector &offsets, + std::vector &outputs, std::unordered_map &txs) const; - void block_longhash_worker(const uint64_t height, const std::vector &blocks, - std::unordered_map &map) const; + /** + * @brief computes the "short" and "long" hashes for a set of blocks + * + * @param height the height of the first block + * @param blocks the blocks to be hashed + * @param map return-by-reference the hashes for each block + */ + void block_longhash_worker(const uint64_t height, const std::vector &blocks, + std::unordered_map &map) const; private: + + // TODO: evaluate whether or not each of these typedefs are left over from blockchain_storage typedef std::unordered_map blocks_by_id_index; + typedef std::unordered_map transactions_container; + typedef std::unordered_set key_images_container; + typedef std::vector blocks_container; + typedef std::unordered_map blocks_ext_by_hash; + typedef std::unordered_map blocks_by_hash; + typedef std::map>> outputs_container; //crypto::hash - tx hash, size_t - index of out in transaction + BlockchainDB* m_db; tx_memory_pool& m_tx_pool; + mutable epee::critical_section m_blockchain_lock; // TODO: add here reader/writer lock // main chain + // TODO: evaluate whether or not each is still needed or left over from blockchain_storage blocks_container m_blocks; // height -> block_extended_info blocks_by_id_index m_blocks_index; // crypto::hash -> height transactions_container m_transactions; size_t m_current_block_cumul_sz_limit; + // metadata containers std::unordered_map>> m_scan_table; std::unordered_map> m_check_tx_inputs_table; std::unordered_map m_blocks_longhash_table; @@ -196,21 +684,21 @@ namespace cryptonote std::vector m_blocks_hash_check; std::vector m_blocks_txs_check; - blockchain_db_sync_mode m_db_sync_mode; - bool m_fast_sync; - bool m_show_time_stats; - uint64_t m_db_blocks_per_sync; - uint64_t m_max_prepare_blocks_threads; + blockchain_db_sync_mode m_db_sync_mode; + bool m_fast_sync; + bool m_show_time_stats; + uint64_t m_db_blocks_per_sync; + uint64_t m_max_prepare_blocks_threads; uint64_t m_fake_pow_calc_time; uint64_t m_fake_scan_time; - uint64_t m_sync_counter; - std::vector m_timestamps; - std::vector m_difficulties; - uint64_t m_timestamps_and_difficulties_height; + uint64_t m_sync_counter; + std::vector m_timestamps; + std::vector m_difficulties; + uint64_t m_timestamps_and_difficulties_height; - boost::asio::io_service m_async_service; - boost::thread_group m_async_pool; - std::unique_ptr m_async_work_idle; + boost::asio::io_service m_async_service; + boost::thread_group m_async_pool; + std::unique_ptr m_async_work_idle; // all alternative chains blocks_ext_by_hash m_alternative_chains; // crypto::hash -> block_extended_info @@ -225,38 +713,339 @@ namespace cryptonote std::atomic m_is_blockchain_storing; bool m_enforce_dns_checkpoints; + /** + * @brief collects the keys for all outputs being "spent" as an input + * + * This function makes sure that each "input" in an input (mixins) exists + * and collects the public key for each from the transaction it was included in + * via the visitor passed to it. + * + * If pmax_related_block_height is not NULL, its value is set to the height + * of the most recent block which contains an output used in the input set + * + * @tparam visitor_t a class encapsulating tx is unlocked and collect tx key + * @param tx_in_to_key a transaction input instance + * @param vis an instance of the visitor to use + * @param tx_prefix_hash the hash of the associated transaction_prefix + * @param pmax_related_block_height return-by-pointer the height of the most recent block in the input set + * + * @return false if any keys are not found or any inputs are not unlocked, otherwise true + */ template inline bool scan_outputkeys_for_indexes(const txin_to_key& tx_in_to_key, visitor_t &vis, const crypto::hash &tx_prefix_hash, uint64_t* pmax_related_block_height = NULL) const; + + /** + * @brief collect output public keys of a transaction input set + * + * This function locates all outputs associated with a given input set (mixins) + * and validates that they exist and are usable + * (unlocked, unspent is checked elsewhere). + * + * If pmax_related_block_height is not NULL, its value is set to the height + * of the most recent block which contains an output used in the input set + * + * @param txin the transaction input + * @param tx_prefix_hash the transaction prefix hash, for caching organization + * @param sig the input signature + * @param output_keys return-by-reference the public keys of the outputs in the input set + * @param pmax_related_block_height return-by-pointer the height of the most recent block in the input set + * + * @return false if any output is not yet unlocked, or is missing, otherwise true + */ bool check_tx_input(const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, std::vector &output_keys, uint64_t* pmax_related_block_height); + + /** + * @brief validate a transaction's inputs and their keys + * + * This function validates transaction inputs and their keys. Previously + * it also performed double spend checking, but that has been moved to its + * own function. + * + * If pmax_related_block_height is not NULL, its value is set to the height + * of the most recent block which contains an output used in any input set + * + * Currently this function calls ring signature validation for each + * transaction. + * + * @param tx the transaction to validate + * @param pmax_related_block_height return-by-pointer the height of the most recent block in the input set + * + * @return false if any validation step fails, otherwise true + */ bool check_tx_inputs(const transaction& tx, uint64_t* pmax_used_block_height = NULL); + /** + * @brief performs a blockchain reorganization according to the longest chain rule + * + * This function aggregates all the actions necessary to switch to a + * newly-longer chain. If any step in the reorganization process fails, + * the blockchain is reverted to its previous state. + * + * @param alt_chain the chain to switch to + * @param discard_disconnected_chain whether or not to keep the old chain as an alternate + * + * @return false if the reorganization fails, otherwise true + */ bool switch_to_alternative_blockchain(std::list& alt_chain, bool discard_disconnected_chain); + + /** + * @brief removes the most recent block from the blockchain + * + * @return the block removed + */ block pop_block_from_blockchain(); + /** + * @brief validate and add a new block to the end of the blockchain + * + * This function is merely a convenience wrapper around the other + * of the same name. This one passes the block's hash to the other + * as well as the block and verification context. + * + * @param bl the block to be added + * @param bvc metadata concerning the block's validity + * + * @return true if the block was added successfully, otherwise false + */ bool handle_block_to_main_chain(const block& bl, block_verification_context& bvc); + + /** + * @brief validate and add a new block to the end of the blockchain + * + * When a block is given to Blockchain to be added to the blockchain, it + * is passed here if it is determined to belong at the end of the current + * chain. + * + * @param bl the block to be added + * @param id the hash of the block + * @param bvc metadata concerning the block's validity + * + * @return true if the block was added successfully, otherwise false + */ bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc); + + /** + * @brief validate and add a new block to an alternate blockchain + * + * If a block to be added does not belong to the main chain, but there + * is an alternate chain to which it should be added, that is handled + * here. + * + * @param b the block to be added + * @param id the hash of the block + * @param bvc metadata concerning the block's validity + * + * @return true if the block was added successfully, otherwise false + */ bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc); + + /** + * @brief gets the difficulty requirement for a new block on an alternate chain + * + * @param alt_chain the chain to be added to + * @param bei the block being added (and metadata, see ::block_extended_info) + * + * @return the difficulty requirement + */ difficulty_type get_next_difficulty_for_alternative_chain(const std::list& alt_chain, block_extended_info& bei) const; + + /** + * @brief sanity checks a miner transaction before validating an entire block + * + * This function merely checks basic things like the structure of the miner + * transaction, the unlock time, and that the amount doesn't overflow. + * + * @param b the block containing the miner transaction + * @param height the height at which the block will be added + * + * @return false if anything is found wrong with the miner transaction, otherwise true + */ bool prevalidate_miner_transaction(const block& b, uint64_t height); + + /** + * @brief validates a miner (coinbase) transaction + * + * This function makes sure that the miner calculated his reward correctly + * and that his miner transaction totals reward + fee. + * + * @param b the block containing the miner transaction to be validated + * @param cumulative_block_size the block's size + * @param fee the total fees collected in the block + * @param base_reward return-by-reference the new block's generated coins + * @param already_generated_coins the amount of currency generated prior to this block + * + * @return false if anything is found wrong with the miner transaction, otherwise true + */ bool validate_miner_transaction(const block& b, size_t cumulative_block_size, uint64_t fee, uint64_t& base_reward, uint64_t already_generated_coins); + + //FIXME: function declared but neither defined nor used, candidate for removal bool validate_transaction(const block& b, uint64_t height, const transaction& tx); + + /** + * @brief reverts the blockchain to its previous state following a failed switch + * + * If Blockchain fails to switch to an alternate chain when it means + * to do so, this function reverts the blockchain to how it was before + * the attempted switch. + * + * @param original_chain the chain to switch back to + * @param rollback_height the height to revert to before appending the original chain + * + * @return false if something goes wrong with reverting (very bad), otherwise true + */ bool rollback_blockchain_switching(std::list& original_chain, uint64_t rollback_height); + + //FIXME: function declared but neither defined nor used, candidate for removal, + // remnant from old blockchain_storage implementation bool add_transaction_from_block(const transaction& tx, const crypto::hash& tx_id, const crypto::hash& bl_id, uint64_t bl_height); + + //FIXME: function declared but neither defined nor used, candidate for removal, + // remnant from old blockchain_storage implementation bool push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector& global_indexes); + + //FIXME: function declared but neither defined nor used, candidate for removal, + // remnant from old blockchain_storage implementation bool pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id); + + /** + * @brief gets recent block sizes for median calculation + * + * get the block sizes of the last blocks, and return by reference . + * + * @param sz return-by-reference the list of sizes + * @param count the number of blocks to get sizes for + */ void get_last_n_blocks_sizes(std::vector& sz, size_t count) const; + + /** + * @brief adds the given output to the requested set of random outputs + * + * @param result_outs return-by-reference the set the output is to be added to + * @param amount the output amount + * @param i the output index (indexed to amount) + */ void add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i) const; + + /** + * @brief checks if a transaction is unlocked (its outputs spendable) + * + * This function checks to see if a transaction is unlocked. + * unlock_time is either a block index or a unix time. + * + * @param unlock_time the unlock parameter (height or time) + * + * @return true if spendable, otherwise false + */ bool is_tx_spendtime_unlocked(uint64_t unlock_time) const; + + /** + * @brief stores an invalid block in a separate container + * + * Storing invalid blocks allows quick dismissal of the same block + * if it is seen again. + * + * @param bl the invalid block + * @param h the block's hash + * + * @return false if the block cannot be stored for some reason, otherwise true + */ bool add_block_as_invalid(const block& bl, const crypto::hash& h); + + /** + * @brief stores an invalid block in a separate container + * + * Storing invalid blocks allows quick dismissal of the same block + * if it is seen again. + * + * @param bei the invalid block (see ::block_extended_info) + * @param h the block's hash + * + * @return false if the block cannot be stored for some reason, otherwise true + */ bool add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h); + + /** + * @brief checks a block's timestamp + * + * This function grabs the timestamps from the most recent blocks, + * where n = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW. If there are not those many + * blocks in the blockchain, the timestap is assumed to be valid. If there + * are, this function returns: + * true if the block's timestamp is not less than the timestamp of the + * median of the selected blocks + * false otherwise + * + * @param b the block to be checked + * + * @return true if the block's timestamp is valid, otherwise false + */ bool check_block_timestamp(const block& b) const; + + /** + * @brief checks a block's timestamp + * + * If the block is not more recent than the median of the recent + * timestamps passed here, it is considered invalid. + * + * @param timestamps a list of the most recent timestamps to check against + * @param b the block to be checked + * + * @return true if the block's timestamp is valid, otherwise false + */ bool check_block_timestamp(std::vector& timestamps, const block& b) const; + + /** + * @brief get the "adjusted time" + * + * Currently this simply returns the current time according to the + * user's machine. + * + * @return the current time + */ uint64_t get_adjusted_time() const; + + /** + * @brief finish an alternate chain's timestamp window from the main chain + * + * for an alternate chain, get the timestamps from the main chain to complete + * the needed number of timestamps for the BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW. + * + * @param start_height the alternate chain's attachment height to the main chain + * @param timestamps return-by-value the timestamps set to be populated + * + * @return true unless start_height is greater than the current blockchain height + */ bool complete_timestamps_vector(uint64_t start_height, std::vector& timestamps); + + /** + * @brief calculate the block size limit for the next block to be added + * + * @return true + */ bool update_next_cumulative_size_limit(); + /** + * @brief make sure a transaction isn't attempting a double-spend + * + * @param tx the transaction to check + * @param keys_this_block a cumulative list of spent keys for the current block + * + * @return false if a double spend was detected, otherwise true + */ bool check_for_double_spend(const transaction& tx, key_images_container& keys_this_block) const; + + //FIXME: function declared but neither defined nor used, candidate for removal, void get_timestamp_and_difficulty(uint64_t ×tamp, difficulty_type &difficulty, const int offset) const; + + /** + * @brief validates a transaction input's ring signature + * + * @param tx_prefix_hash the transaction prefix' hash + * @param key_image the key image generated from the true input + * @param pubkeys the public keys for each input in the ring signature + * @param sig the signature generated for each input in the ring signature + * @param result false if the ring signature is invalid, otherwise true + */ void check_ring_signature(const crypto::hash &tx_prefix_hash, const crypto::key_image &key_image, const std::vector &pubkeys, const std::vector &sig, uint64_t &result); }; From 3ba43b385ead26f92eadac98015c6770816a9403 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Thu, 24 Sep 2015 11:26:17 -0400 Subject: [PATCH 02/11] doxygen include private and static members This can be easily reverted or removed before this branch is merged, so I'm going ahead and committing these couple changes. --- Doxyfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doxyfile b/Doxyfile index a70ef812b..a2700b347 100644 --- a/Doxyfile +++ b/Doxyfile @@ -409,13 +409,13 @@ LOOKUP_CACHE_SIZE = 0 # normally produced when WARNINGS is set to YES. # The default value is: NO. -EXTRACT_ALL = NO +EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. @@ -427,7 +427,7 @@ EXTRACT_PACKAGE = NO # included in the documentation. # The default value is: NO. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO @@ -452,7 +452,7 @@ EXTRACT_LOCAL_METHODS = NO # are hidden. # The default value is: NO. -EXTRACT_ANON_NSPACES = NO +EXTRACT_ANON_NSPACES = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these From 94f7615c573fbc4b9d476ba994cf290f90dc8bf4 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:25:06 -0400 Subject: [PATCH 03/11] Remove unnecessary or defunct code --- src/cryptonote_core/blockchain.cpp | 49 ------------------------------ src/cryptonote_core/blockchain.h | 21 ------------- 2 files changed, 70 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index b3d05fa3e..2b587a4d2 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -100,55 +100,6 @@ m_is_blockchain_storing(false), m_enforce_dns_checkpoints(false), m_max_prepare_ LOG_PRINT_L3("Blockchain::" << __func__); } //------------------------------------------------------------------ -//TODO: is this still needed? I don't think so - tewinget -template -void Blockchain::serialize(archive_t & ar, const unsigned int version) -{ - key_images_container dummy_key_images_container; - - LOG_PRINT_L3("Blockchain::" << __func__); - if(version < 11) - return; - CRITICAL_REGION_LOCAL(m_blockchain_lock); - ar & m_blocks; - ar & m_blocks_index; - ar & m_transactions; - ar & dummy_key_images_container; - ar & m_alternative_chains; - ar & m_outputs; - ar & m_invalid_blocks; - ar & m_current_block_cumul_sz_limit; - /*serialization bug workaround*/ - if(version > 11) - { - uint64_t total_check_count = m_db->height() + m_blocks_index.size() + m_transactions.size() + dummy_key_images_container.size() + m_alternative_chains.size() + m_outputs.size() + m_invalid_blocks.size() + m_current_block_cumul_sz_limit; - if(archive_t::is_saving::value) - { - ar & total_check_count; - } - else - { - uint64_t total_check_count_loaded = 0; - ar & total_check_count_loaded; - if(total_check_count != total_check_count_loaded) - { - LOG_ERROR("Blockchain storage data corruption detected. total_count loaded from file = " << total_check_count_loaded << ", expected = " << total_check_count); - - LOG_PRINT_L0("Blockchain storage:" << std::endl << "m_blocks: " << m_db->height() << std::endl << "m_blocks_index: " << m_blocks_index.size() << std::endl << "m_transactions: " << m_transactions.size() << std::endl << "dummy_key_images_container: " << dummy_key_images_container.size() << std::endl << "m_alternative_chains: " << m_alternative_chains.size() << std::endl << "m_outputs: " << m_outputs.size() << std::endl << "m_invalid_blocks: " << m_invalid_blocks.size() << std::endl << "m_current_block_cumul_sz_limit: " << m_current_block_cumul_sz_limit); - - throw std::runtime_error("Blockchain data corruption"); - } - } - } - - if (version > 12) - { - ar & *m_hardfork; - } - - LOG_PRINT_L3("Blockchain storage:" << std::endl << "m_blocks: " << m_db->height() << std::endl << "m_blocks_index: " << m_blocks_index.size() << std::endl << "m_transactions: " << m_transactions.size() << std::endl << "dummy_key_images_container: " << dummy_key_images_container.size() << std::endl << "m_alternative_chains: " << m_alternative_chains.size() << std::endl << "m_outputs: " << m_outputs.size() << std::endl << "m_invalid_blocks: " << m_invalid_blocks.size() << std::endl << "m_current_block_cumul_sz_limit: " << m_current_block_cumul_sz_limit); -} -//------------------------------------------------------------------ bool Blockchain::have_tx(const crypto::hash &id) const { LOG_PRINT_L3("Blockchain::" << __func__); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index e132da5f0..333cbe5c7 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -420,9 +420,6 @@ namespace cryptonote */ bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp); - //FIXME: function declared, but never defined or used. Candidate for removal. - bool handle_get_objects(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res); - /** * @brief gets random outputs to mix with * @@ -887,9 +884,6 @@ namespace cryptonote */ bool validate_miner_transaction(const block& b, size_t cumulative_block_size, uint64_t fee, uint64_t& base_reward, uint64_t already_generated_coins); - //FIXME: function declared but neither defined nor used, candidate for removal - bool validate_transaction(const block& b, uint64_t height, const transaction& tx); - /** * @brief reverts the blockchain to its previous state following a failed switch * @@ -904,18 +898,6 @@ namespace cryptonote */ bool rollback_blockchain_switching(std::list& original_chain, uint64_t rollback_height); - //FIXME: function declared but neither defined nor used, candidate for removal, - // remnant from old blockchain_storage implementation - bool add_transaction_from_block(const transaction& tx, const crypto::hash& tx_id, const crypto::hash& bl_id, uint64_t bl_height); - - //FIXME: function declared but neither defined nor used, candidate for removal, - // remnant from old blockchain_storage implementation - bool push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector& global_indexes); - - //FIXME: function declared but neither defined nor used, candidate for removal, - // remnant from old blockchain_storage implementation - bool pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id); - /** * @brief gets recent block sizes for median calculation * @@ -1043,9 +1025,6 @@ namespace cryptonote */ bool check_for_double_spend(const transaction& tx, key_images_container& keys_this_block) const; - //FIXME: function declared but neither defined nor used, candidate for removal, - void get_timestamp_and_difficulty(uint64_t ×tamp, difficulty_type &difficulty, const int offset) const; - /** * @brief validates a transaction input's ring signature * From 6fe7aedae9e52cb98187a060d0633871468c47d9 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:11 -0400 Subject: [PATCH 04/11] minor bugfixes and refactoring - Blockchain should store if it's running on testnet or not - moved loading compiled-in block hashes to its own function for clarity - on handle_get_objects, should now correctly return false if a block's transactions are missing - replace instances of BOOST_FOREACH with C++11 for loops in Blockchain. --- src/cryptonote_core/blockchain.cpp | 138 +++++++++++++++++------------ src/cryptonote_core/blockchain.h | 12 ++- 2 files changed, 91 insertions(+), 59 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 2b587a4d2..53fcfda6a 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -249,7 +249,9 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet) m_db = db; - if (testnet) { + m_testnet = testnet; + + if (m_testnet) { m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till); for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n) m_hardfork->add(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].time); @@ -271,7 +273,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet) LOG_PRINT_L0("Blockchain not loaded, generating genesis block."); block bl = boost::value_initialized(); block_verification_context bvc = boost::value_initialized(); - if (testnet) + if (m_testnet) { generate_genesis_block(bl, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE); } @@ -302,45 +304,8 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet) // we only need 1 m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service)); - //TODO: move this block into separate functions? #if defined(PER_BLOCK_CHECKPOINT) - if (m_fast_sync && !testnet && get_blocks_dat_start() != nullptr) - { - if (get_blocks_dat_size() > 4) - { - const unsigned char *p = get_blocks_dat_start(); - uint32_t nblocks = *(uint32_t *) p; - if(nblocks > 0 && nblocks > m_db->height()) - { - LOG_PRINT_L0("Loading precomputed blocks: " << nblocks); - p += sizeof(uint32_t); - for (uint32_t i = 0; i < nblocks; i++) - { - crypto::hash hash; - memcpy(hash.data, p, sizeof(hash.data)); - p += sizeof(hash.data); - m_blocks_hash_check.push_back(hash); - } - - // FIXME: clear tx_pool because the process might have been - // terminated and caused it to store txs kept by blocks. - // The core will not call check_tx_inputs(..) for these - // transactions in this case. Consequently, the sanity check - // for tx hashes will fail in handle_block_to_main_chain(..) - std::list txs; - m_tx_pool.get_transactions(txs); - - size_t blob_size; - uint64_t fee; - transaction pool_tx; - for(const transaction &tx : txs) - { - crypto::hash tx_hash = get_transaction_hash(tx); - m_tx_pool.take_tx(tx_hash, pool_tx, blob_size, fee); - } - } - } - } + load_compiled_in_block_hashes(); #endif LOG_PRINT_GREEN("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block(), LOG_LEVEL_0); @@ -616,10 +581,10 @@ void Blockchain::get_all_known_block_ids(std::list &main, std::lis main.push_back(a); } - BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_alternative_chains) + for (const blocks_ext_by_hash::value_type &v : m_alternative_chains) alt.push_back(v.first); - BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_invalid_blocks) + for (const blocks_ext_by_hash::value_type &v : m_invalid_blocks) invalid.push_back(v.first); } //------------------------------------------------------------------ @@ -800,7 +765,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list last_blocks_sizes; @@ -1004,7 +969,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m size_t real_txs_size = 0; uint64_t real_fee = 0; CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock); - BOOST_FOREACH(crypto::hash &cur_hash, b.tx_hashes) + for (crypto::hash &cur_hash : b.tx_hashes) { auto cur_res = m_tx_pool.m_transactions.find(cur_hash); if (cur_res == m_tx_pool.m_transactions.end()) @@ -1365,31 +1330,47 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO std::list blocks; get_blocks(arg.blocks, blocks, rsp.missed_ids); - BOOST_FOREACH(const auto& bl, blocks) + for (const auto& bl : blocks) { - std::list missed_tx_id; + std::list missed_tx_ids; std::list txs; - // FIXME: s/rsp.missed_ids/missed_tx_id/ ? Seems like rsp.missed_ids - // is for missed blocks, not missed transactions as well. - get_transactions(bl.tx_hashes, txs, rsp.missed_ids); - CHECK_AND_ASSERT_MES(!missed_tx_id.size(), false, "Internal error: has missed missed_tx_id.size()=" << missed_tx_id.size() - << std::endl << "for block id = " << get_block_hash(bl)); + get_transactions(bl.tx_hashes, txs, missed_tx_ids); + + if (missed_tx_ids.size() != 0) + { + LOG_ERROR("Error retrieving blocks, missed " << missed_tx_ids.size() + << " transactions for block with hash: " << get_block_hash(bl) + << std::endl + ); + rsp.missed_ids.push_back(get_block_hash(bl)); + + // append missed transaction hashes to response missed_ids field, + // as done below if any standalone transactions were requested + // and missed. + rsp.missed_ids.splice(rsp.missed_ids.end(), missed_tx_ids); + return false; + } + rsp.blocks.push_back(block_complete_entry()); block_complete_entry& e = rsp.blocks.back(); //pack block e.block = t_serializable_object_to_blob(bl); //pack transactions - BOOST_FOREACH(transaction& tx, txs) - e.txs.push_back(t_serializable_object_to_blob(tx)); + for (transaction& tx : txs) + { + e.txs.push_back(t_serializable_object_to_blob(tx)); + } } //get another transactions, if need std::list txs; get_transactions(arg.txs, txs, rsp.missed_ids); //pack aside transactions - BOOST_FOREACH(const auto& tx, txs) - rsp.txs.push_back(t_serializable_object_to_blob(tx)); + for (const auto& tx : txs) + { + rsp.txs.push_back(t_serializable_object_to_blob(tx)); + } return true; } @@ -1399,7 +1380,7 @@ bool Blockchain::get_alternative_blocks(std::list& blocks) const LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); - BOOST_FOREACH(const auto& alt_bl, m_alternative_chains) + for (const auto& alt_bl : m_alternative_chains) { blocks.push_back(alt_bl.second.bl); } @@ -1942,7 +1923,7 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const { LOG_PRINT_L3("Blockchain::" << __func__); - BOOST_FOREACH(const txin_v& in, tx.vin) + for (const txin_v& in : tx.vin) { CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, in_to_key, true); if(have_tx_keyimg_as_spent(in_to_key.k_image)) @@ -3154,3 +3135,44 @@ bool Blockchain::get_hard_fork_voting_info(uint8_t version, uint32_t &window, ui { return m_hardfork->get_voting_info(version, window, votes, threshold, voting); } + +void Blockchain::load_compiled_in_block_hashes() +{ + if (m_fast_sync && !m_testnet && get_blocks_dat_start() != nullptr) + { + if (get_blocks_dat_size() > 4) + { + const unsigned char *p = get_blocks_dat_start(); + uint32_t nblocks = *(uint32_t *) p; + if(nblocks > 0 && nblocks > m_db->height()) + { + LOG_PRINT_L0("Loading precomputed blocks: " << nblocks); + p += sizeof(uint32_t); + for (uint32_t i = 0; i < nblocks; i++) + { + crypto::hash hash; + memcpy(hash.data, p, sizeof(hash.data)); + p += sizeof(hash.data); + m_blocks_hash_check.push_back(hash); + } + + // FIXME: clear tx_pool because the process might have been + // terminated and caused it to store txs kept by blocks. + // The core will not call check_tx_inputs(..) for these + // transactions in this case. Consequently, the sanity check + // for tx hashes will fail in handle_block_to_main_chain(..) + std::list txs; + m_tx_pool.get_transactions(txs); + + size_t blob_size; + uint64_t fee; + transaction pool_tx; + for(const transaction &tx : txs) + { + crypto::hash tx_hash = get_transaction_hash(tx); + m_tx_pool.take_tx(tx_hash, pool_tx, blob_size, fee); + } + } + } + } +} diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 333cbe5c7..0673e7ed7 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -719,6 +719,8 @@ namespace cryptonote HardFork *m_hardfork; + bool m_testnet; + /** * @brief collects the keys for all outputs being "spent" as an input * @@ -1036,8 +1038,16 @@ namespace cryptonote */ void check_ring_signature(const crypto::hash &tx_prefix_hash, const crypto::key_image &key_image, const std::vector &pubkeys, const std::vector &sig, uint64_t &result); - }; + /** + * @brief loads block hashes from compiled-in data set + * + * A (possibly empty) set of block hashes can be compiled into the + * monero daemon binary. This function loads those hashes into + * a useful state. + */ + void load_compiled_in_block_hashes(); + }; /************************************************************************/ /* */ From 910bcc077d0eabe23af48fbed70024fd3783f2df Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:26 -0400 Subject: [PATCH 05/11] documentation updates to Blockchain Reviewed and updated or removed FIXME and TODO comments --- src/cryptonote_core/blockchain.cpp | 40 +++++++++++------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 53fcfda6a..922e29d8f 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -229,8 +229,6 @@ uint64_t Blockchain::get_current_blockchain_height() const return m_db->height(); } //------------------------------------------------------------------ -//FIXME: possibly move this into the constructor, to avoid accidentally -// dereferencing a null BlockchainDB pointer bool Blockchain::init(BlockchainDB* db, const bool testnet) { LOG_PRINT_L3("Blockchain::" << __func__); @@ -265,9 +263,6 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet) m_hardfork->init(); // if the blockchain is new, add the genesis block - // this feels kinda kludgy to do it this way, but can be looked at later. - // TODO: add function to create and store genesis block, - // taking testnet into account if(!m_db->height()) { LOG_PRINT_L0("Blockchain not loaded, generating genesis block."); @@ -731,9 +726,6 @@ bool Blockchain::switch_to_alternative_blockchain(std::listsecond, get_block_hash(ch_ent->second.bl)); LOG_PRINT_L1("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl)); m_alternative_chains.erase(ch_ent); @@ -1011,10 +1003,13 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m #endif /* - two-phase miner transaction generation: we don't know exact block size until we prepare block, but we don't know reward until we know - block size, so first miner transaction generated with fake amount of money, and with phase we know think we know expected block size + * two-phase miner transaction generation: we don't know exact block size + * until we prepare the block, but we don't know the reward until we know + * the block size, so the miner transaction is generated with a fake amount + * of money. After the block is filled with transactions and the block + * size is known, the miner transaction is updated to reflect the correct + * amount (fees + block reward). */ - //make blocks coin-base tx looks close to real coinbase tx to get truthful blob size bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, 11); CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance"); size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx); @@ -1238,7 +1233,8 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist"); alt_chain.push_back(i_res.first); - // FIXME: is it even possible for a checkpoint to show up not on the main chain? + // if somehow this block belongs to the main chain according to + // checkpoints, make it so. if(is_a_checkpoint) { //do reorganize! @@ -1315,13 +1311,8 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list& qbloc return true; } //------------------------------------------------------------------ -//FIXME: change argument to std::vector, low priority // find split point between ours and foreign blockchain (or start at // blockchain height ), and return up to max_count FULL // blocks by reference. @@ -1884,9 +1874,10 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); +//FIXME: there seems to be no code path where this function would be called +// AND the conditions of this if would be met, consider removing. #if defined(PER_BLOCK_CHECKPOINT) // check if we're doing per-block checkpointing - // FIXME: investigate why this block returns if (m_db->height() < m_blocks_hash_check.size() && kept_by_block) { TIME_MEASURE_START(a); @@ -2345,8 +2336,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& // before checkpoints, which is very dangerous behaviour. We moved the PoW // validation out of the next chunk of code to make sure that we correctly // check PoW now. - // FIXME: height parameter is not used...should it be used or should it not - // be a parameter? + // // validate proof_of_work versus difficulty target bool precomputed = false; #if defined(PER_BLOCK_CHECKPOINT) @@ -2490,7 +2480,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& { LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); - //TODO: why is this done? make sure that keeping invalid blocks makes sense. + //FIXME: why is this done? make sure that keeping invalid blocks makes sense. add_block_as_invalid(bl, id); LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions"); bvc.m_verifivation_failed = true; From 04055a0634c1794f1dd8c9e3d0728e3681253646 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:31 -0400 Subject: [PATCH 06/11] doxygen documentation for checkpoints.{h,cpp} All functions in src/cryptonote_core/checkpoints.h are now documented in doxygen style. checkpoints.cpp has been reviewed, one function has been marked for discussion on correctness. --- src/cryptonote_core/checkpoints.cpp | 5 +- src/cryptonote_core/checkpoints.h | 100 +++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 6 deletions(-) diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_core/checkpoints.cpp index e4223afb5..0b1c211a3 100644 --- a/src/cryptonote_core/checkpoints.cpp +++ b/src/cryptonote_core/checkpoints.cpp @@ -84,10 +84,7 @@ namespace cryptonote return check_block(height, h, ignored); } //--------------------------------------------------------------------------- - // this basically says if the blockchain is smaller than the first - // checkpoint then alternate blocks are allowed. Alternatively, if the - // last checkpoint *before* the end of the current chain is also before - // the block to be added, then this is fine. + //FIXME: is this the desired behavior? bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const { if (0 == block_height) diff --git a/src/cryptonote_core/checkpoints.h b/src/cryptonote_core/checkpoints.h index 55d765b71..f972d59b8 100644 --- a/src/cryptonote_core/checkpoints.h +++ b/src/cryptonote_core/checkpoints.h @@ -36,19 +36,115 @@ namespace cryptonote { + /** + * @brief A container for blockchain checkpoints + * + * A checkpoint is a pre-defined hash for the block at a given height. + * Some of these are compiled-in, while others can be loaded at runtime + * either from a json file or via DNS from a checkpoint-hosting server. + */ class checkpoints { public: + + /** + * @brief default constructor + */ checkpoints(); + + /** + * @brief adds a checkpoint to the container + * + * @param height the height of the block the checkpoint is for + * @param hash_str the hash of the block, as a string + * + * @return false if parsing the hash fails, or if the height is a duplicate + * AND the existing checkpoint hash does not match the new one, + * otherwise returns true + */ bool add_checkpoint(uint64_t height, const std::string& hash_str); + + /** + * @brief checks if there is a checkpoint in the future + * + * This function checks if the height passed is lower than the highest + * checkpoint. + * + * @param height the height to check against + * + * @return false if no checkpoints, otherwise returns whether or not + * the height passed is lower than the highest checkpoint. + */ bool is_in_checkpoint_zone(uint64_t height) const; - bool check_block(uint64_t height, const crypto::hash& h) const; + + /** + * @brief checks if the given height and hash agree with the checkpoints + * + * This function checks if the given height and hash exist in the + * checkpoints container. If so, it returns whether or not the passed + * parameters match the stored values. + * + * @param height the height to be checked + * @param h the hash to be checked + * @param is_a_checkpoint return-by-reference if there is a checkpoint at the given height + * + * @return true if there is no checkpoint at the given height, + * true if the passed parameters match the stored checkpoint, + * false otherwise + */ bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const; + + /** + * @overload + */ + bool check_block(uint64_t height, const crypto::hash& h) const; + + /** + * @brief checks if alternate chain blocks should be kept for a given height + * + * this basically says if the blockchain is smaller than the first + * checkpoint then alternate blocks are allowed. Alternatively, if the + * last checkpoint *before* the end of the current chain is also before + * the block to be added, then this is fine. + * + * @param blockchain_height the current blockchain height + * @param block_height the height of the block to be added as alternate + * + * @return true if alternate blocks are allowed given the parameters, + * otherwise false + */ bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const; + + /** + * @brief gets the highest checkpoint height + * + * @return the height of the highest checkpoint + */ uint64_t get_max_height() const; + + /** + * @brief gets the checkpoints container + * + * @return a const reference to the checkpoints container + */ const std::map& get_points() const; + + /** + * @brief checks if our checkpoints container conflicts with another + * + * A conflict refers to a case where both checkpoint sets have a checkpoint + * for a specific height but their hashes for that height do not match. + * + * @param other the other checkpoints instance to check against + * + * @return false if any conflict is found, otherwise true + */ bool check_for_conflicts(const checkpoints& other) const; + + private: - std::map m_points; + + std::map m_points; //!< the checkpoints container + }; } From 37fa7b44d69225dfa855cb0e7fe10d53d515e402 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:37 -0400 Subject: [PATCH 07/11] Move checkpoint functions into checkpoints class The functions in src/cryptonote_core/checkpoints_create.{h,cpp} should be member functions of the checkpoints class, if nothing else for the sake of keeping their documentation together. This commit covers moving those functions to be member functions of the checkpoints class as well as documenting those functions. --- src/cryptonote_core/CMakeLists.txt | 2 - src/cryptonote_core/blockchain.cpp | 8 +- src/cryptonote_core/blockchain_storage.cpp | 8 +- src/cryptonote_core/checkpoints.cpp | 226 +++++++++++++++++ src/cryptonote_core/checkpoints.h | 67 +++++ src/cryptonote_core/checkpoints_create.cpp | 271 --------------------- src/cryptonote_core/checkpoints_create.h | 48 ---- src/cryptonote_core/cryptonote_core.cpp | 4 +- src/daemon/core.h | 1 - 9 files changed, 303 insertions(+), 332 deletions(-) delete mode 100644 src/cryptonote_core/checkpoints_create.cpp delete mode 100644 src/cryptonote_core/checkpoints_create.h diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 7b0a5017d..c8bc490e0 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -31,7 +31,6 @@ set(cryptonote_core_sources blockchain_storage.cpp blockchain.cpp checkpoints.cpp - checkpoints_create.cpp cryptonote_basic_impl.cpp cryptonote_core.cpp cryptonote_format_utils.cpp @@ -49,7 +48,6 @@ set(cryptonote_core_private_headers blockchain_storage_boost_serialization.h blockchain.h checkpoints.h - checkpoints_create.h connection_context.h cryptonote_basic.h cryptonote_basic_impl.h diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 922e29d8f..c340a37d4 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -49,7 +49,7 @@ #include "common/boost_serialization_helper.h" #include "warnings.h" #include "crypto/hash.h" -#include "cryptonote_core/checkpoints_create.h" +#include "cryptonote_core/checkpoints.h" #if defined(PER_BLOCK_CHECKPOINT) #include "blocks/blocks.h" #endif @@ -2673,7 +2673,7 @@ void Blockchain::check_against_checkpoints(const checkpoints& points, bool enfor // with an existing checkpoint. bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns) { - if (!cryptonote::load_checkpoints_from_json(m_checkpoints, file_path)) + if (!m_checkpoints.load_checkpoints_from_json(file_path)) { return false; } @@ -2682,7 +2682,7 @@ bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns // if we're not hard-enforcing dns checkpoints, handle accordingly if (m_enforce_dns_checkpoints && check_dns) { - if (!cryptonote::load_checkpoints_from_dns(m_checkpoints)) + if (!m_checkpoints.load_checkpoints_from_dns()) { return false; } @@ -2690,7 +2690,7 @@ bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns else if (check_dns) { checkpoints dns_points; - cryptonote::load_checkpoints_from_dns(dns_points); + dns_points.load_checkpoints_from_dns(); if (m_checkpoints.check_for_conflicts(dns_points)) { check_against_checkpoints(dns_points, false); diff --git a/src/cryptonote_core/blockchain_storage.cpp b/src/cryptonote_core/blockchain_storage.cpp index 4a4d348ba..a4d18f2ef 100644 --- a/src/cryptonote_core/blockchain_storage.cpp +++ b/src/cryptonote_core/blockchain_storage.cpp @@ -48,7 +48,7 @@ #include "common/boost_serialization_helper.h" #include "warnings.h" #include "crypto/hash.h" -#include "cryptonote_core/checkpoints_create.h" +#include "cryptonote_core/checkpoints.h" //#include "serialization/json_archive.h" #include "../../contrib/otshell_utils/utils.hpp" #include "../../src/p2p/data_logger.hpp" @@ -1853,7 +1853,7 @@ void blockchain_storage::check_against_checkpoints(const checkpoints& points, bo // with an existing checkpoint. bool blockchain_storage::update_checkpoints(const std::string& file_path, bool check_dns) { - if (!cryptonote::load_checkpoints_from_json(m_checkpoints, file_path)) + if (!m_checkpoints.load_checkpoints_from_json(file_path)) { return false; } @@ -1862,7 +1862,7 @@ bool blockchain_storage::update_checkpoints(const std::string& file_path, bool c // if we're not hard-enforcing dns checkpoints, handle accordingly if (m_enforce_dns_checkpoints && check_dns) { - if (!cryptonote::load_checkpoints_from_dns(m_checkpoints)) + if (!m_checkpoints.load_checkpoints_from_dns()) { return false; } @@ -1870,7 +1870,7 @@ bool blockchain_storage::update_checkpoints(const std::string& file_path, bool c else if (check_dns) { checkpoints dns_points; - cryptonote::load_checkpoints_from_dns(dns_points, m_testnet); + dns_points.load_checkpoints_from_dns(m_testnet); if (m_checkpoints.check_for_conflicts(dns_points)) { check_against_checkpoints(dns_points, false); diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_core/checkpoints.cpp index 0b1c211a3..9eb85c6c0 100644 --- a/src/cryptonote_core/checkpoints.cpp +++ b/src/cryptonote_core/checkpoints.cpp @@ -29,10 +29,40 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "include_base_utils.h" + using namespace epee; #include "checkpoints.h" +#include "common/dns_utils.h" +#include "include_base_utils.h" +#include +#include + +namespace +{ + bool dns_records_match(const std::vector& a, const std::vector& b) + { + if (a.size() != b.size()) return false; + + for (const auto& record_in_a : a) + { + bool ok = false; + for (const auto& record_in_b : b) + { + if (record_in_a == record_in_b) + { + ok = true; + break; + } + } + if (!ok) return false; + } + + return true; + } +} // anonymous namespace + namespace cryptonote { //--------------------------------------------------------------------------- @@ -125,4 +155,200 @@ namespace cryptonote } return true; } + + bool checkpoints::init_default_checkpoints() + { + ADD_CHECKPOINT(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148"); + ADD_CHECKPOINT(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381"); + ADD_CHECKPOINT(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d"); + ADD_CHECKPOINT(1000, "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876"); + ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2"); + ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25"); + ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6"); + ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c"); + ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3"); + ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698"); + ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2"); + ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb"); + ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063"); + ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553"); + ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61"); + ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf"); + ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131"); + ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8"); + ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d"); + ADD_CHECKPOINT(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831"); + + return true; + } + + bool checkpoints::load_checkpoints_from_json(const std::string json_hashfile_fullpath) + { + boost::system::error_code errcode; + if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode))) + { + LOG_PRINT_L1("Blockchain checkpoints file not found"); + return true; + } + + LOG_PRINT_L1("Adding checkpoints from blockchain hashfile"); + + uint64_t prev_max_height = get_max_height(); + LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height); + t_hash_json hashes; + epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath); + for (std::vector::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); ) + { + uint64_t height; + height = it->height; + if (height <= prev_max_height) { + LOG_PRINT_L1("ignoring checkpoint height " << height); + } else { + std::string blockhash = it->hash; + LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash); + ADD_CHECKPOINT(height, blockhash); + } + ++it; + } + + return true; + } + + bool checkpoints::load_checkpoints_from_dns(bool testnet) + { + // All four MoneroPulse domains have DNSSEC on and valid + static const std::vector dns_urls = { "checkpoints.moneropulse.se" + , "checkpoints.moneropulse.org" + , "checkpoints.moneropulse.net" + , "checkpoints.moneropulse.co" + }; + + static const std::vector testnet_dns_urls = { "testpoints.moneropulse.se" + , "testpoints.moneropulse.org" + , "testpoints.moneropulse.net" + , "testpoints.moneropulse.co" + }; + + std::vector > records; + records.resize(dns_urls.size()); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(0, dns_urls.size() - 1); + size_t first_index = dis(gen); + + bool avail, valid; + size_t cur_index = first_index; + do + { + std::string url; + if (testnet) + { + url = testnet_dns_urls[cur_index]; + } + else + { + url = dns_urls[cur_index]; + } + + records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid); + if (!avail) + { + records[cur_index].clear(); + LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping."); + } + if (!valid) + { + records[cur_index].clear(); + LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping."); + } + + cur_index++; + if (cur_index == dns_urls.size()) + { + cur_index = 0; + } + records[cur_index].clear(); + } while (cur_index != first_index); + + size_t num_valid_records = 0; + + for( const auto& record_set : records) + { + if (record_set.size() != 0) + { + num_valid_records++; + } + } + + if (num_valid_records < 2) + { + LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received"); + return true; + } + + int good_records_index = -1; + for (size_t i = 0; i < records.size() - 1; ++i) + { + if (records[i].size() == 0) continue; + + for (size_t j = i + 1; j < records.size(); ++j) + { + if (dns_records_match(records[i], records[j])) + { + good_records_index = i; + break; + } + } + if (good_records_index >= 0) break; + } + + if (good_records_index < 0) + { + LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched"); + return true; + } + + for (auto& record : records[good_records_index]) + { + auto pos = record.find(":"); + if (pos != std::string::npos) + { + uint64_t height; + crypto::hash hash; + + // parse the first part as uint64_t, + // if this fails move on to the next record + std::stringstream ss(record.substr(0, pos)); + if (!(ss >> height)) + { + continue; + } + + // parse the second part as crypto::hash, + // if this fails move on to the next record + std::string hashStr = record.substr(pos + 1); + if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash)) + { + continue; + } + + ADD_CHECKPOINT(height, hashStr); + } + } + return true; + } + + bool checkpoints::load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet, bool dns) + { + bool result; + + result = load_checkpoints_from_json(json_hashfile_fullpath); + if (dns) + { + result &= load_checkpoints_from_dns(testnet); + } + + return result; + } } diff --git a/src/cryptonote_core/checkpoints.h b/src/cryptonote_core/checkpoints.h index f972d59b8..06ef3c5ca 100644 --- a/src/cryptonote_core/checkpoints.h +++ b/src/cryptonote_core/checkpoints.h @@ -32,6 +32,11 @@ #include #include #include "cryptonote_basic_impl.h" +#include "misc_log_ex.h" +#include "storages/portable_storage_template_helper.h" // epee json include + +#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(add_checkpoint(h, hash), false); +#define JSON_HASH_FILE_NAME "checkpoints.json" namespace cryptonote @@ -141,9 +146,71 @@ namespace cryptonote */ bool check_for_conflicts(const checkpoints& other) const; + /** + * @brief loads the default main chain checkpoints + * + * @return true unless adding a checkpoint fails + */ + bool init_default_checkpoints(); + + /** + * @brief load new checkpoints + * + * Loads new checkpoints from the specified json file, as well as + * (optionally) from DNS. + * + * @param json_hashfile_fullpath path to the json checkpoints file + * @param testnet whether to load testnet checkpoints or mainnet + * @param dns whether or not to load DNS checkpoints + * + * @return true if loading successful and no conflicts + */ + bool load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet=false, bool dns=true); + + /** + * @brief load new checkpoints from json + * + * @param json_hashfile_fullpath path to the json checkpoints file + * + * @return true if loading successful and no conflicts + */ + bool load_checkpoints_from_json(const std::string json_hashfile_fullpath); + + /** + * @brief load new checkpoints from DNS + * + * @param testnet whether to load testnet checkpoints or mainnet + * + * @return true if loading successful and no conflicts + */ + bool load_checkpoints_from_dns(bool testnet = false); private: + + /** + * @brief struct for loading a checkpoint from json + */ + struct t_hashline + { + uint64_t height; //!< the height of the checkpoint + std::string hash; //!< the hash for the checkpoint + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(height) + KV_SERIALIZE(hash) + END_KV_SERIALIZE_MAP() + }; + + /** + * @brief struct for loading many checkpoints from json + */ + struct t_hash_json { + std::vector hashlines; //!< the checkpoint lines from the file + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(hashlines) + END_KV_SERIALIZE_MAP() + }; + std::map m_points; //!< the checkpoints container }; diff --git a/src/cryptonote_core/checkpoints_create.cpp b/src/cryptonote_core/checkpoints_create.cpp deleted file mode 100644 index d9bfa9807..000000000 --- a/src/cryptonote_core/checkpoints_create.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (c) 2014-2015, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// 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 - -#include "checkpoints_create.h" -#include "common/dns_utils.h" -#include "include_base_utils.h" -#include -#include -#include "storages/portable_storage_template_helper.h" // epee json include - -namespace -{ - bool dns_records_match(const std::vector& a, const std::vector& b) - { - if (a.size() != b.size()) return false; - - for (const auto& record_in_a : a) - { - bool ok = false; - for (const auto& record_in_b : b) - { - if (record_in_a == record_in_b) - { - ok = true; - break; - } - } - if (!ok) return false; - } - - return true; - } -} // anonymous namespace - -namespace cryptonote -{ - -struct t_hashline -{ - uint64_t height; - std::string hash; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - KV_SERIALIZE(hash) - END_KV_SERIALIZE_MAP() -}; - -struct t_hash_json { - std::vector hashlines; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hashlines) - END_KV_SERIALIZE_MAP() -}; - -bool create_checkpoints(cryptonote::checkpoints& checkpoints) -{ - ADD_CHECKPOINT(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148"); - ADD_CHECKPOINT(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381"); - ADD_CHECKPOINT(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d"); - ADD_CHECKPOINT(1000, "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876"); - ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2"); - ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25"); - ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6"); - ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c"); - ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3"); - ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698"); - ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2"); - ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb"); - ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063"); - ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553"); - ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61"); - ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf"); - ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131"); - ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8"); - ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d"); - ADD_CHECKPOINT(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831"); - - return true; -} - -bool load_checkpoints_from_json(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath) -{ - boost::system::error_code errcode; - if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode))) - { - LOG_PRINT_L1("Blockchain checkpoints file not found"); - return true; - } - - LOG_PRINT_L1("Adding checkpoints from blockchain hashfile"); - - uint64_t prev_max_height = checkpoints.get_max_height(); - LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height); - t_hash_json hashes; - epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath); - for (std::vector::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); ) - { - uint64_t height; - height = it->height; - if (height <= prev_max_height) { - LOG_PRINT_L1("ignoring checkpoint height " << height); - } else { - std::string blockhash = it->hash; - LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash); - ADD_CHECKPOINT(height, blockhash); - } - ++it; - } - - return true; -} - -bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testnet) -{ - // All four MoneroPulse domains have DNSSEC on and valid - static const std::vector dns_urls = { "checkpoints.moneropulse.se" - , "checkpoints.moneropulse.org" - , "checkpoints.moneropulse.net" - , "checkpoints.moneropulse.co" - }; - - static const std::vector testnet_dns_urls = { "testpoints.moneropulse.se" - , "testpoints.moneropulse.org" - , "testpoints.moneropulse.net" - , "testpoints.moneropulse.co" - }; - - std::vector > records; - records.resize(dns_urls.size()); - - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution dis(0, dns_urls.size() - 1); - size_t first_index = dis(gen); - - bool avail, valid; - size_t cur_index = first_index; - do - { - std::string url; - if (testnet) - { - url = testnet_dns_urls[cur_index]; - } - else - { - url = dns_urls[cur_index]; - } - - records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid); - if (!avail) - { - records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping."); - } - if (!valid) - { - records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping."); - } - - cur_index++; - if (cur_index == dns_urls.size()) - { - cur_index = 0; - } - records[cur_index].clear(); - } while (cur_index != first_index); - - size_t num_valid_records = 0; - - for( const auto& record_set : records) - { - if (record_set.size() != 0) - { - num_valid_records++; - } - } - - if (num_valid_records < 2) - { - LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received"); - return true; - } - - int good_records_index = -1; - for (size_t i = 0; i < records.size() - 1; ++i) - { - if (records[i].size() == 0) continue; - - for (size_t j = i + 1; j < records.size(); ++j) - { - if (dns_records_match(records[i], records[j])) - { - good_records_index = i; - break; - } - } - if (good_records_index >= 0) break; - } - - if (good_records_index < 0) - { - LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched"); - return true; - } - - for (auto& record : records[good_records_index]) - { - auto pos = record.find(":"); - if (pos != std::string::npos) - { - uint64_t height; - crypto::hash hash; - - // parse the first part as uint64_t, - // if this fails move on to the next record - std::stringstream ss(record.substr(0, pos)); - if (!(ss >> height)) - { - continue; - } - - // parse the second part as crypto::hash, - // if this fails move on to the next record - std::string hashStr = record.substr(pos + 1); - if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash)) - { - continue; - } - - ADD_CHECKPOINT(height, hashStr); - } - } - return true; -} - -bool load_new_checkpoints(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath) -{ - // TODO: replace hard-coded url with const string or #define - return (load_checkpoints_from_json(checkpoints, json_hashfile_fullpath) && load_checkpoints_from_dns(checkpoints)); -} - -} // namespace cryptonote diff --git a/src/cryptonote_core/checkpoints_create.h b/src/cryptonote_core/checkpoints_create.h deleted file mode 100644 index 8422e2b33..000000000 --- a/src/cryptonote_core/checkpoints_create.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2014-2015, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// 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 "checkpoints.h" -#include "misc_log_ex.h" - -#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(checkpoints.add_checkpoint(h, hash), false); -#define JSON_HASH_FILE_NAME "checkpoints.json" - -namespace cryptonote -{ - - bool create_checkpoints(cryptonote::checkpoints& checkpoints); - - bool load_checkpoints_from_json(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath); - bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testnet = false); - bool load_new_checkpoints(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath); - -} // namespace cryptonote diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 4ade50cde..da6c33e44 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -43,7 +43,7 @@ using namespace epee; #include "misc_language.h" #include #include "daemon/command_line_args.h" -#include "cryptonote_core/checkpoints_create.h" +#include "cryptonote_core/checkpoints.h" #include "blockchain_db/blockchain_db.h" #include "blockchain_db/lmdb/db_lmdb.h" #if defined(BERKELEY_DB) @@ -146,7 +146,7 @@ namespace cryptonote if (!m_testnet) { cryptonote::checkpoints checkpoints; - if (!cryptonote::create_checkpoints(checkpoints)) + if (!checkpoints.init_default_checkpoints()) { throw std::runtime_error("Failed to initialize checkpoints"); } diff --git a/src/daemon/core.h b/src/daemon/core.h index c3d84454d..b67032749 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -28,7 +28,6 @@ #pragma once -#include "cryptonote_core/checkpoints_create.h" #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "misc_log_ex.h" From f2cc3a9eaf51bb91c3fa8aff2dc8c796872cfe42 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:43 -0400 Subject: [PATCH 08/11] doxygen documentation for difficulty functions --- src/cryptonote_core/difficulty.cpp | 8 ++++--- src/cryptonote_core/difficulty.h | 37 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp index 2b5466791..a2f7a794c 100644 --- a/src/cryptonote_core/difficulty.cpp +++ b/src/cryptonote_core/difficulty.cpp @@ -116,8 +116,8 @@ namespace cryptonote { return !carry; } - difficulty_type next_difficulty(vector timestamps, vector cumulative_difficulties, size_t target_seconds) { - //cutoff DIFFICULTY_LAG + difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds) { + if(timestamps.size() > DIFFICULTY_WINDOW) { timestamps.resize(DIFFICULTY_WINDOW); @@ -151,13 +151,15 @@ namespace cryptonote { assert(total_work > 0); uint64_t low, high; mul(total_work, target_seconds, low, high); + // blockchain errors "difficulty overhead" if this function returns zero. + // TODO: consider throwing an exception instead if (high != 0 || low + time_span - 1 < low) { return 0; } return (low + time_span - 1) / time_span; } - difficulty_type next_difficulty(vector timestamps, vector cumulative_difficulties) + difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties) { return next_difficulty(std::move(timestamps), std::move(cumulative_difficulties), DIFFICULTY_TARGET); } diff --git a/src/cryptonote_core/difficulty.h b/src/cryptonote_core/difficulty.h index 42d2df500..d1b36ed9b 100644 --- a/src/cryptonote_core/difficulty.h +++ b/src/cryptonote_core/difficulty.h @@ -39,7 +39,44 @@ namespace cryptonote { typedef std::uint64_t difficulty_type; + /** + * @brief checks if a hash fits the given difficulty + * + * The hash passes if (hash * difficulty) < 2^192. + * Phrased differently, if (hash * difficulty) fits without overflow into + * the least significant 192 bits of the 256 bit multiplication result. + * + * @param hash the hash to check + * @param difficulty the difficulty to check against + * + * @return true if valid, else false + */ bool check_hash(const crypto::hash &hash, difficulty_type difficulty); + + /** + * @brief gets the required difficulty for the next block + * + * This function calculates the required difficulty for the block that + * follows the blocks to which the passed timestamps and difficulties + * belong. + * + * The current difficulty algorithm is as follows: + * - take the total time and cumulative difficulty ("total work") + * - let m = the total work multiplied by the target block time + * - if (m + total time) > 2^64, give 0 for the next difficulty, + * the blockchain class treats this as an error "difficulty overhead" + * + * - the next difficulty = (m + the total time - 1) / the total time + * + * @param timestamps the most recent timestamps + * @param cumulative_difficulties the most recent difficulties + * + * @return the required difficulty for the next block + */ difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties); + + /** + * @overload + */ difficulty_type next_difficulty(std::vector timestamps, std::vector cumulative_difficulties, size_t target_seconds); } From 9366319367e86f5802de30607f1f22772e171bda Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:51 -0400 Subject: [PATCH 09/11] cryptonote::core doxygen documentation --- src/cryptonote_core/cryptonote_core.cpp | 2 +- src/cryptonote_core/cryptonote_core.h | 616 ++++++++++++++++++++++-- 2 files changed, 590 insertions(+), 28 deletions(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index da6c33e44..0637d0d76 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -338,7 +338,7 @@ namespace cryptonote CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); r = m_miner.init(vm, m_testnet); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); + CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance"); return load_state_data(); } diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 634340a3f..3110c03f1 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -55,152 +55,714 @@ DISABLE_VS_WARNINGS(4355) namespace cryptonote { - /************************************************************************/ - /* */ - /************************************************************************/ + + /** + * @brief handles core cryptonote functionality + * + * This class coordinates cryptonote functionality including, but not + * limited to, communication among the Blockchain, the transaction pool, + * any miners, and the network. + */ class core: public i_miner_handler { public: + + /** + * @brief constructor + * + * sets member variables into a usable state + * + * @param pprotocol pre-constructed protocol object to store and use + */ core(i_cryptonote_protocol* pprotocol); + + /** + * @copydoc Blockchain::handle_get_objects + * + * @note see Blockchain::handle_get_objects() + * @param context connection context associated with the request + */ bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp, cryptonote_connection_context& context); + + /** + * @brief calls various idle routines + * + * @note see miner::on_idle and tx_memory_pool::on_idle + * + * @return true + */ bool on_idle(); + + /** + * @brief handles an incoming transaction + * + * Parses an incoming transaction and, if nothing is obviously wrong, + * passes it along to the transaction pool + * + * @param tx_blob the tx to handle + * @param tvc metadata about the transaction's validity + * @param keeped_by_block if the transaction has been in a block + * + * @return true if the transaction made it to the transaction pool, otherwise false + */ bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block); + + /** + * @brief handles an incoming block + * + * periodic update to checkpoints is triggered here + * Attempts to add the block to the Blockchain and, on success, + * optionally updates the miner's block template. + * + * @param block_blob the block to be added + * @param bvc return-by-reference metadata context about the block's validity + * @param update_miner_blocktemplate whether or not to update the miner's block template + * + * @return false if loading new checkpoints fails, or the block is not + * added, otherwise true + */ bool handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate = true); + + /** + * @copydoc Blockchain::prepare_handle_incoming_blocks + * + * @note see Blockchain::prepare_handle_incoming_blocks + */ bool prepare_handle_incoming_blocks(const std::list &blocks); + + /** + * @copydoc Blockchain::cleanup_handle_incoming_blocks + * + * @note see Blockchain::cleanup_handle_incoming_blocks + */ bool cleanup_handle_incoming_blocks(bool force_sync = false); + /** + * @brief check the size of a block against the current maximum + * + * @param block_blob the block to check + * + * @return whether or not the block is too big + */ bool check_incoming_block_size(const blobdata& block_blob) const; + + /** + * @brief get the cryptonote protocol instance + * + * @return the instance + */ i_cryptonote_protocol* get_protocol(){return m_pprotocol;} //-------------------- i_miner_handler ----------------------- + + /** + * @brief stores and relays a block found by a miner + * + * Updates the miner's target block, attempts to store the found + * block in Blockchain, and -- on success -- relays that block to + * the network. + * + * @param b the block found + * + * @return true if the block was added to the main chain, otherwise false + */ virtual bool handle_block_found( block& b); + + /** + * @copydoc Blockchain::create_block_template + * + * @note see Blockchain::create_block_template + */ virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce); + /** + * @brief gets the miner instance + * + * @return a reference to the miner instance + */ miner& get_miner(){return m_miner;} + + /** + * @brief gets the miner instance (const) + * + * @return a const reference to the miner instance + */ const miner& get_miner()const{return m_miner;} + + /** + * @brief adds command line options to the given options set + * + * As of now, there are no command line options specific to core, + * so this function simply returns. + * + * @param desc return-by-reference the command line options set to add to + */ static void init_options(boost::program_options::options_description& desc); + + /** + * @brief initializes the core as needed + * + * This function initializes the transaction pool, the Blockchain, and + * a miner instance with parameters given on the command line (or defaults) + * + * @param vm command line parameters + * + * @return false if one of the init steps fails, otherwise true + */ bool init(const boost::program_options::variables_map& vm); + + /** + * @copydoc Blockchain::reset_and_set_genesis_block + * + * @note see Blockchain::reset_and_set_genesis_block + */ bool set_genesis_block(const block& b); + + /** + * @brief performs safe shutdown steps for core and core components + * + * Uninitializes the miner instance, transaction pool, and Blockchain + * + * if m_fast_exit is set, the call to Blockchain::deinit() is not made. + * + * @return true + */ bool deinit(); + + /** + * @brief sets fast exit flag + * + * @note see deinit() + */ static void set_fast_exit(); + + /** + * @brief gets the current state of the fast exit flag + * + * @return the fast exit flag + * + * @note see deinit() + */ static bool get_fast_exit(); + + /** + * @brief sets to drop blocks downloaded (for testing) + */ void test_drop_download(); + + /** + * @brief sets to drop blocks downloaded below a certain height + * + * @param height height below which to drop blocks + */ void test_drop_download_height(uint64_t height); + + /** + * @brief gets whether or not to drop blocks (for testing) + * + * @return whether or not to drop blocks + */ bool get_test_drop_download() const; + + /** + * @brief gets whether or not to drop blocks + * + * If the current blockchain height <= our block drop threshold + * and test drop blocks is set, return true + * + * @return see above + */ bool get_test_drop_download_height() const; + + /** + * @copydoc Blockchain::get_current_blockchain_height + * + * @note see Blockchain::get_current_blockchain_height() + */ uint64_t get_current_blockchain_height() const; bool get_blockchain_top(uint64_t& heeight, crypto::hash& top_id) const; + + /** + * @brief get the hash and height of the most recent block + * + * @param height return-by-reference height of the block + * @param top_id return-by-reference hash of the block + * + * @return true + */ + bool get_blockchain_top(uint64_t& height, crypto::hash& top_id) const; + + /** + * @copydoc Blockchain::get_blocks(uint64_t, size_t, std::list&, std::list&) const + * + * @note see Blockchain::get_blocks(uint64_t, size_t, std::list&, std::list&) const + */ bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs) const; + + /** + * @copydoc Blockchain::get_blocks(uint64_t, size_t, std::list&) const + * + * @note see Blockchain::get_blocks(uint64_t, size_t, std::list&) const + */ bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks) const; + + /** + * @copydoc Blockchain::get_blocks(const t_ids_container&, t_blocks_container&, t_missed_container&) const + * + * @note see Blockchain::get_blocks(const t_ids_container&, t_blocks_container&, t_missed_container&) const + */ template bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const { return m_blockchain_storage.get_blocks(block_ids, blocks, missed_bs); } + + /** + * @copydoc Blockchain::get_block_id_by_height + * + * @note see Blockchain::get_block_id_by_height + */ crypto::hash get_block_id_by_height(uint64_t height) const; + + /** + * @copydoc Blockchain::get_transactions + * + * @note see Blockchain::get_transactions + */ bool get_transactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs) const; + + /** + * @copydoc Blockchain::get_block_by_hash + * + * @note see Blockchain::get_block_by_hash + */ bool get_block_by_hash(const crypto::hash &h, block &blk) const; //void get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid); + /** + * @copydoc Blockchain::get_alternative_blocks + * + * @note see Blockchain::get_alternative_blocks(std::list&) const + */ bool get_alternative_blocks(std::list& blocks) const; + + /** + * @copydoc Blockchain::get_alternative_blocks_count + * + * @note see Blockchain::get_alternative_blocks_count() const + */ size_t get_alternative_blocks_count() const; + /** + * @brief set the pointer to the cryptonote protocol object to use + * + * @param pprotocol the pointer to set ours as + */ void set_cryptonote_protocol(i_cryptonote_protocol* pprotocol); + + /** + * @copydoc Blockchain::set_checkpoints + * + * @note see Blockchain::set_checkpoints() + */ void set_checkpoints(checkpoints&& chk_pts); + + /** + * @brief set the file path to read from when loading checkpoints + * + * @param path the path to set ours as + */ void set_checkpoints_file_path(const std::string& path); + + /** + * @brief set whether or not we enforce DNS checkpoints + * + * @param enforce_dns enforce DNS checkpoints or not + */ void set_enforce_dns_checkpoints(bool enforce_dns); + /** + * @copydoc tx_memory_pool::get_transactions + * + * @note see tx_memory_pool::get_transactions + */ bool get_pool_transactions(std::list& txs) const; + + /** + * @copydoc tx_memory_pool::get_pool_transactions_and_spent_keys_info + * + * @note see tx_memory_pool::get_pool_transactions_and_spent_keys_info + */ bool get_pool_transactions_and_spent_keys_info(std::vector& tx_infos, std::vector& key_image_infos) const; + + /** + * @copydoc tx_memory_pool::get_transactions_count + * + * @note see tx_memory_pool::get_transactions_count + */ size_t get_pool_transactions_count() const; + + /** + * @copydoc Blockchain::get_total_transactions + * + * @note see Blockchain::get_total_transactions + */ size_t get_blockchain_total_transactions() const; //bool get_outs(uint64_t amount, std::list& pkeys); + + /** + * @copydoc Blockchain::have_block + * + * @note see Blockchain::have_block + */ bool have_block(const crypto::hash& id) const; + + /** + * @copydoc Blockchain::get_short_chain_history + * + * @note see Blockchain::get_short_chain_history + */ bool get_short_chain_history(std::list& ids) const; + + /** + * @copydoc Blockchain::find_blockchain_supplement(const std::list&, NOTIFY_RESPONSE_CHAIN_ENTRY::request&) const + * + * @note see Blockchain::find_blockchain_supplement(const std::list&, NOTIFY_RESPONSE_CHAIN_ENTRY::request&) const + */ bool find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const; + + /** + * @copydoc Blockchain::find_blockchain_supplement(const uint64_t, const std::list&, std::list > >&, uint64_t&, uint64_t&, size_t) const + * + * @note see Blockchain::find_blockchain_supplement(const uint64_t, const std::list&, std::list > >&, uint64_t&, uint64_t&, size_t) const + */ bool find_blockchain_supplement(const uint64_t req_start_block, const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const; + + /** + * @brief gets some stats about the daemon + * + * @param st_inf return-by-reference container for the stats requested + * + * @return true + */ bool get_stat_info(core_stat_info& st_inf) const; //bool get_backward_blocks_sizes(uint64_t from_height, std::vector& sizes, size_t count); + + /** + * @copydoc Blockchain::get_tx_outputs_gindexs + * + * @note see Blockchain::get_tx_outputs_gindexs + */ bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs) const; + + /** + * @copydoc Blockchain::get_tail_id + * + * @note see Blockchain::get_tail_id + */ crypto::hash get_tail_id() const; + + /** + * @copydoc Blockchain::get_random_outs_for_amounts + * + * @note see Blockchain::get_random_outs_for_amounts + */ bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const; + + + /** + * @copydoc miner::pause + * + * @note see miner::pause + */ void pause_mine(); + + /** + * @copydoc miner::resume + * + * @note see miner::resume + */ void resume_mine(); + #if BLOCKCHAIN_DB == DB_LMDB + /** + * @brief gets the Blockchain instance + * + * @return a reference to the Blockchain instance + */ Blockchain& get_blockchain_storage(){return m_blockchain_storage;} + + /** + * @brief gets the Blockchain instance (const) + * + * @return a const reference to the Blockchain instance + */ const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;} #else blockchain_storage& get_blockchain_storage(){return m_blockchain_storage;} const blockchain_storage& get_blockchain_storage()const{return m_blockchain_storage;} #endif - //debug functions + + /** + * @copydoc Blockchain::print_blockchain + * + * @note see Blockchain::print_blockchain + */ void print_blockchain(uint64_t start_index, uint64_t end_index) const; + + /** + * @copydoc Blockchain::print_blockchain_index + * + * @note see Blockchain::print_blockchain_index + */ void print_blockchain_index() const; + + /** + * @copydoc tx_memory_pool::print_pool + * + * @note see tx_memory_pool::print_pool + */ std::string print_pool(bool short_format) const; + + /** + * @copydoc Blockchain::print_blockchain_outs + * + * @note see Blockchain::print_blockchain_outs + */ void print_blockchain_outs(const std::string& file); + + /** + * @copydoc miner::on_synchronized + * + * @note see miner::on_synchronized + */ void on_synchronized(); + /** + * @brief sets the target blockchain height + * + * @param target_blockchain_height the height to set + */ void set_target_blockchain_height(uint64_t target_blockchain_height); + + /** + * @brief gets the target blockchain height + * + * @param target_blockchain_height the target height + */ uint64_t get_target_blockchain_height() const; + /** + * @brief tells the Blockchain to update its checkpoints + * + * This function will check if enough time has passed since the last + * time checkpoints were updated and tell the Blockchain to update + * its checkpoints if it is time. If updating checkpoints fails, + * the daemon is told to shut down. + * + * @note see Blockchain::update_checkpoints() + */ bool update_checkpoints(); + /** + * @brief tells the daemon to wind down operations and stop running + * + * Currently this function raises SIGTERM, allowing the installed signal + * handlers to do the actual stopping. + */ + void graceful_exit(); + + /** + * @brief stops the daemon running + * + * @note see graceful_exit() + */ void stop(); + /** + * @copydoc Blockchain::have_tx_keyimg_as_spent + * + * @note see Blockchain::have_tx_keyimg_as_spent + */ bool is_key_image_spent(const crypto::key_image& key_im) const; + + /** + * @brief check if multiple key images are spent + * + * plural version of is_key_image_spent() + * + * @param key_im list of key images to check + * @param spent return-by-reference result for each image checked + * + * @return true + */ bool are_key_images_spent(const std::vector& key_im, std::vector &spent) const; private: + + /** + * @copydoc add_new_tx(const transaction&, tx_verification_context&, bool) + * + * @param tx_hash the transaction's hash + * @param tx_prefix_hash the transaction prefix' hash + * @param blob_size the size of the transaction + * + */ bool add_new_tx(const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block); + + /** + * @brief add a new transaction to the transaction pool + * + * Adds a new transaction to the transaction pool. + * + * @param tx the transaction to add + * @param tvc return-by-reference metadata about the transaction's verification process + * @param keeped_by_block whether or not the transaction has been in a block + * + * @return true if the transaction is already in the transaction pool, + * is already in a block on the Blockchain, or is successfully added + * to the transaction pool + */ bool add_new_tx(const transaction& tx, tx_verification_context& tvc, bool keeped_by_block); + + /** + * @copydoc Blockchain::add_new_block + * + * @note see Blockchain::add_new_block + */ bool add_new_block(const block& b, block_verification_context& bvc); + + /** + * @brief load any core state stored on disk + * + * currently does nothing, but may have state to load in the future. + * + * @return true + */ bool load_state_data(); + + /** + * @copydoc parse_tx_from_blob(transaction&, crypto::hash&, crypto::hash&, const blobdata&) const + * + * @note see parse_tx_from_blob(transaction&, crypto::hash&, crypto::hash&, const blobdata&) const + */ bool parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash, const blobdata& blob) const; + /** + * @brief check a transaction's syntax + * + * For now this does nothing, but it may check something about the tx + * in the future. + * + * @param tx the transaction to check + * + * @return true + */ bool check_tx_syntax(const transaction& tx) const; //check correct values, amounts and all lightweight checks not related with database + + /** + * @brief validates some simple properties of a transaction + * + * Currently checks: tx has inputs, + * tx inputs all of supported type(s), + * tx outputs valid (type, key, amount), + * input and output total amounts don't overflow, + * output amount <= input amount, + * tx not too large, + * each input has a different key image. + * + * @param tx the transaction to check + * @param keeped_by_block if the transaction has been in a block + * + * @return true if all the checks pass, otherwise false + */ bool check_tx_semantic(const transaction& tx, bool keeped_by_block) const; //check if tx already in memory pool or in main blockchain bool check_tx_ring_signature(const txin_to_key& tx, const crypto::hash& tx_prefix_hash, const std::vector& sig) const; bool is_tx_spendtime_unlocked(uint64_t unlock_time) const; + /** + * @copydoc miner::on_block_chain_update + * + * @note see miner::on_block_chain_update + * + * @return true + */ bool update_miner_block_template(); + + /** + * @brief act on a set of command line options given + * + * @param vm the command line options + * + * @return true + */ bool handle_command_line(const boost::program_options::variables_map& vm); bool on_update_blocktemplate_interval(); - bool check_tx_inputs_keyimages_diff(const transaction& tx) const; - void graceful_exit(); - bool check_fork_time(); - static std::atomic m_fast_exit; - bool m_test_drop_download = true; - uint64_t m_test_drop_download_height = 0; - tx_memory_pool m_mempool; + /** + * @brief verify that each input key image in a transaction is unique + * + * @param tx the transaction to check + * + * @return false if any key image is repeated, otherwise true + */ + bool check_tx_inputs_keyimages_diff(const transaction& tx) const; + + /** + * @brief checks HardFork status and prints messages about it + * + * Checks the status of HardFork and logs/prints if an update to + * the daemon is necessary. + * + * @note see Blockchain::get_hard_fork_state and HardFork::State + * + * @return true + */ + bool check_fork_time(); + + static std::atomic m_fast_exit; //!< whether or not to deinit Blockchain on exit + + bool m_test_drop_download = true; //!< whether or not to drop incoming blocks (for testing) + + uint64_t m_test_drop_download_height = 0; //!< height under which to drop incoming blocks, if doing so + + tx_memory_pool m_mempool; //!< transaction pool instance #if BLOCKCHAIN_DB == DB_LMDB - Blockchain m_blockchain_storage; + Blockchain m_blockchain_storage; //!< Blockchain instance #else blockchain_storage m_blockchain_storage; #endif - i_cryptonote_protocol* m_pprotocol; - epee::critical_section m_incoming_tx_lock; + + i_cryptonote_protocol* m_pprotocol; //!< cryptonote protocol instance + + epee::critical_section m_incoming_tx_lock; //!< incoming transaction lock + //m_miner and m_miner_addres are probably temporary here - miner m_miner; - account_public_address m_miner_address; - std::string m_config_folder; - cryptonote_protocol_stub m_protocol_stub; - epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval; - epee::math_helper::once_a_time_seconds<60*60*2, false> m_fork_moaner; friend class tx_validate_inputs; - std::atomic m_starter_message_showed; + miner m_miner; //!< miner instance + account_public_address m_miner_address; //!< address to mine to (for miner instance) - uint64_t m_target_blockchain_height; + std::string m_config_folder; //!< folder to look in for configs and other files - bool m_testnet; - std::string m_checkpoints_path; - time_t m_last_dns_checkpoints_update; - time_t m_last_json_checkpoints_update; + cryptonote_protocol_stub m_protocol_stub; //!< cryptonote protocol stub instance - std::atomic_flag m_checkpoints_updating; + epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval; //!< interval for manual storing of Blockchain, if enabled + epee::math_helper::once_a_time_seconds<60*60*2, false> m_fork_moaner; //!< interval for checking HardFork status + + std::atomic m_starter_message_showed; //!< has the "daemon will sync now" message been shown? + + uint64_t m_target_blockchain_height; //!< blockchain height target + + bool m_testnet; //!< are we on testnet? + + std::string m_checkpoints_path; //!< path to json checkpoints file + time_t m_last_dns_checkpoints_update; //!< time when dns checkpoints were last updated + time_t m_last_json_checkpoints_update; //!< time when json checkpoints were last updated + + std::atomic_flag m_checkpoints_updating; //!< set if checkpoints are currently updating to avoid multiple threads attempting to update at once }; } From 31896712c05a5bca63128a2a3061ba07935b913f Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:54 -0400 Subject: [PATCH 10/11] remove defunct code from cryptonote::core --- src/cryptonote_core/cryptonote_core.cpp | 13 ------------- src/cryptonote_core/cryptonote_core.h | 10 ---------- 2 files changed, 23 deletions(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 0637d0d76..621e1b803 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -556,11 +556,6 @@ namespace cryptonote return m_blockchain_storage.get_total_transactions(); } //----------------------------------------------------------------------------------------------- - //bool core::get_outs(uint64_t amount, std::list& pkeys) - //{ - // return m_blockchain_storage.get_outs(amount, pkeys); - //} - //----------------------------------------------------------------------------------------------- bool core::add_new_tx(const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block) { if(m_mempool.have_tx(tx_hash)) @@ -670,10 +665,6 @@ namespace cryptonote { m_miner.on_synchronized(); } - //bool core::get_backward_blocks_sizes(uint64_t from_height, std::vector& sizes, size_t count) - //{ - // return m_blockchain_storage.get_backward_blocks_sizes(from_height, sizes, count); - //} //----------------------------------------------------------------------------------------------- bool core::add_new_block(const block& b, block_verification_context& bvc) { @@ -794,10 +785,6 @@ namespace cryptonote return m_blockchain_storage.get_block_by_hash(h, blk); } //----------------------------------------------------------------------------------------------- - //void core::get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid) { - // m_blockchain_storage.get_all_known_block_ids(main, alt, invalid); - //} - //----------------------------------------------------------------------------------------------- std::string core::print_pool(bool short_format) const { return m_mempool.print_pool(short_format); diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 3110c03f1..26b2bdc3f 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -281,7 +281,6 @@ namespace cryptonote * @note see Blockchain::get_current_blockchain_height() */ uint64_t get_current_blockchain_height() const; - bool get_blockchain_top(uint64_t& heeight, crypto::hash& top_id) const; /** * @brief get the hash and height of the most recent block @@ -338,7 +337,6 @@ namespace cryptonote * @note see Blockchain::get_block_by_hash */ bool get_block_by_hash(const crypto::hash &h, block &blk) const; - //void get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid); /** * @copydoc Blockchain::get_alternative_blocks @@ -409,7 +407,6 @@ namespace cryptonote * @note see Blockchain::get_total_transactions */ size_t get_blockchain_total_transactions() const; - //bool get_outs(uint64_t amount, std::list& pkeys); /** * @copydoc Blockchain::have_block @@ -447,7 +444,6 @@ namespace cryptonote * @return true */ bool get_stat_info(core_stat_info& st_inf) const; - //bool get_backward_blocks_sizes(uint64_t from_height, std::vector& sizes, size_t count); /** * @copydoc Blockchain::get_tx_outputs_gindexs @@ -660,7 +656,6 @@ namespace cryptonote * @return true */ bool check_tx_syntax(const transaction& tx) const; - //check correct values, amounts and all lightweight checks not related with database /** * @brief validates some simple properties of a transaction @@ -679,10 +674,7 @@ namespace cryptonote * @return true if all the checks pass, otherwise false */ bool check_tx_semantic(const transaction& tx, bool keeped_by_block) const; - //check if tx already in memory pool or in main blockchain - bool check_tx_ring_signature(const txin_to_key& tx, const crypto::hash& tx_prefix_hash, const std::vector& sig) const; - bool is_tx_spendtime_unlocked(uint64_t unlock_time) const; /** * @copydoc miner::on_block_chain_update * @@ -700,7 +692,6 @@ namespace cryptonote * @return true */ bool handle_command_line(const boost::program_options::variables_map& vm); - bool on_update_blocktemplate_interval(); /** * @brief verify that each input key image in a transaction is unique @@ -741,7 +732,6 @@ namespace cryptonote epee::critical_section m_incoming_tx_lock; //!< incoming transaction lock //m_miner and m_miner_addres are probably temporary here - friend class tx_validate_inputs; miner m_miner; //!< miner instance account_public_address m_miner_address; //!< address to mine to (for miner instance) From 4adba9bf3b3de73c31f2c34eb6afa284935373d5 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 7 Oct 2015 22:28:59 -0400 Subject: [PATCH 11/11] Change Doxyfile, Blockchain not blockchain_storage Changes the Doxyfile to expand preprocessor macros, but only the ones defined in the Doxyfile. This way we can specify that BLOCKCHAIN_DB == DB_LMDB for the sake of documentation. --- Doxyfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doxyfile b/Doxyfile index a2700b347..93a5c6e76 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1902,7 +1902,7 @@ ENABLE_PREPROCESSING = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then # the macro expansion is limited to the macros specified with the PREDEFINED and @@ -1910,7 +1910,7 @@ MACRO_EXPANSION = NO # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES the includes files in the # INCLUDE_PATH will be searched if a #include is found. @@ -1942,7 +1942,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = "BLOCKCHAIN_DB=2" \ # DB_LMDB # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The