mirror of
https://github.com/monero-project/monero.git
synced 2025-01-28 18:56:31 +02:00
Merge pull request #434
4adba9b
Change Doxyfile, Blockchain not blockchain_storage (Thomas Winget)3189671
remove defunct code from cryptonote::core (Thomas Winget)9366319
cryptonote::core doxygen documentation (Thomas Winget)f2cc3a9
doxygen documentation for difficulty functions (Thomas Winget)37fa7b4
Move checkpoint functions into checkpoints class (Thomas Winget)04055a0
doxygen documentation for checkpoints.{h,cpp} (Thomas Winget)910bcc0
documentation updates to Blockchain (Thomas Winget)6fe7aed
minor bugfixes and refactoring (Thomas Winget)94f7615
Remove unnecessary or defunct code (Thomas Winget)3ba43b3
doxygen include private and static members (Thomas Winget)a3834f9
Updated documentation for blockchain.* (Thomas Winget)
This commit is contained in:
commit
e92ea7976e
14
Doxyfile
14
Doxyfile
@ -409,13 +409,13 @@ LOOKUP_CACHE_SIZE = 0
|
|||||||
# normally produced when WARNINGS is set to YES.
|
# normally produced when WARNINGS is set to YES.
|
||||||
# The default value is: NO.
|
# 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
|
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
|
||||||
# be included in the documentation.
|
# be included in the documentation.
|
||||||
# The default value is: NO.
|
# 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
|
# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
|
||||||
# scope will be included in the documentation.
|
# scope will be included in the documentation.
|
||||||
@ -427,7 +427,7 @@ EXTRACT_PACKAGE = NO
|
|||||||
# included in the documentation.
|
# included in the documentation.
|
||||||
# The default value is: NO.
|
# 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
|
# 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
|
# locally in source files will be included in the documentation. If set to NO
|
||||||
@ -452,7 +452,7 @@ EXTRACT_LOCAL_METHODS = NO
|
|||||||
# are hidden.
|
# are hidden.
|
||||||
# The default value is: NO.
|
# 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
|
# 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
|
# undocumented members inside documented classes or files. If set to NO these
|
||||||
@ -1902,7 +1902,7 @@ ENABLE_PREPROCESSING = YES
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# 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
|
# 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
|
# 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.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# 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
|
# If the SEARCH_INCLUDES tag is set to YES the includes files in the
|
||||||
# INCLUDE_PATH will be searched if a #include is found.
|
# 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.
|
# recursively expanded use the := operator instead of the = operator.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# 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
|
# 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
|
# tag can be used to specify a list of macro names that should be expanded. The
|
||||||
|
@ -31,7 +31,6 @@ set(cryptonote_core_sources
|
|||||||
blockchain_storage.cpp
|
blockchain_storage.cpp
|
||||||
blockchain.cpp
|
blockchain.cpp
|
||||||
checkpoints.cpp
|
checkpoints.cpp
|
||||||
checkpoints_create.cpp
|
|
||||||
cryptonote_basic_impl.cpp
|
cryptonote_basic_impl.cpp
|
||||||
cryptonote_core.cpp
|
cryptonote_core.cpp
|
||||||
cryptonote_format_utils.cpp
|
cryptonote_format_utils.cpp
|
||||||
@ -49,7 +48,6 @@ set(cryptonote_core_private_headers
|
|||||||
blockchain_storage_boost_serialization.h
|
blockchain_storage_boost_serialization.h
|
||||||
blockchain.h
|
blockchain.h
|
||||||
checkpoints.h
|
checkpoints.h
|
||||||
checkpoints_create.h
|
|
||||||
connection_context.h
|
connection_context.h
|
||||||
cryptonote_basic.h
|
cryptonote_basic.h
|
||||||
cryptonote_basic_impl.h
|
cryptonote_basic_impl.h
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
#include "common/boost_serialization_helper.h"
|
#include "common/boost_serialization_helper.h"
|
||||||
#include "warnings.h"
|
#include "warnings.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
#include "cryptonote_core/checkpoints_create.h"
|
#include "cryptonote_core/checkpoints.h"
|
||||||
#if defined(PER_BLOCK_CHECKPOINT)
|
#if defined(PER_BLOCK_CHECKPOINT)
|
||||||
#include "blocks/blocks.h"
|
#include "blocks/blocks.h"
|
||||||
#endif
|
#endif
|
||||||
@ -100,55 +100,6 @@ m_is_blockchain_storing(false), m_enforce_dns_checkpoints(false), m_max_prepare_
|
|||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
//TODO: is this still needed? I don't think so - tewinget
|
|
||||||
template<class archive_t>
|
|
||||||
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
|
bool Blockchain::have_tx(const crypto::hash &id) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
@ -278,8 +229,6 @@ uint64_t Blockchain::get_current_blockchain_height() const
|
|||||||
return m_db->height();
|
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)
|
bool Blockchain::init(BlockchainDB* db, const bool testnet)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
@ -298,7 +247,9 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet)
|
|||||||
|
|
||||||
m_db = db;
|
m_db = db;
|
||||||
|
|
||||||
if (testnet) {
|
m_testnet = testnet;
|
||||||
|
|
||||||
|
if (m_testnet) {
|
||||||
m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
|
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)
|
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);
|
m_hardfork->add(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].time);
|
||||||
@ -312,15 +263,12 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet)
|
|||||||
m_hardfork->init();
|
m_hardfork->init();
|
||||||
|
|
||||||
// if the blockchain is new, add the genesis block
|
// 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())
|
if(!m_db->height())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Blockchain not loaded, generating genesis block.");
|
LOG_PRINT_L0("Blockchain not loaded, generating genesis block.");
|
||||||
block bl = boost::value_initialized<block>();
|
block bl = boost::value_initialized<block>();
|
||||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||||
if (testnet)
|
if (m_testnet)
|
||||||
{
|
{
|
||||||
generate_genesis_block(bl, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
|
generate_genesis_block(bl, config::testnet::GENESIS_TX, config::testnet::GENESIS_NONCE);
|
||||||
}
|
}
|
||||||
@ -352,43 +300,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet)
|
|||||||
m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
|
m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
|
||||||
|
|
||||||
#if defined(PER_BLOCK_CHECKPOINT)
|
#if defined(PER_BLOCK_CHECKPOINT)
|
||||||
if (m_fast_sync && !testnet && get_blocks_dat_start() != nullptr)
|
load_compiled_in_block_hashes();
|
||||||
{
|
|
||||||
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<transaction> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#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);
|
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);
|
||||||
@ -664,10 +576,10 @@ void Blockchain::get_all_known_block_ids(std::list<crypto::hash> &main, std::lis
|
|||||||
main.push_back(a);
|
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);
|
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);
|
invalid.push_back(v.first);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
@ -814,9 +726,6 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
|
|||||||
// just the latter (because the rollback was done above).
|
// just the latter (because the rollback was done above).
|
||||||
rollback_blockchain_switching(disconnected_chain, split_height);
|
rollback_blockchain_switching(disconnected_chain, split_height);
|
||||||
|
|
||||||
// FIXME: Why do we keep invalid blocks around? Possibly in case we hear
|
|
||||||
// about them again so we can immediately dismiss them, but needs some
|
|
||||||
// looking into.
|
|
||||||
add_block_as_invalid(ch_ent->second, get_block_hash(ch_ent->second.bl));
|
add_block_as_invalid(ch_ent->second, 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));
|
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);
|
m_alternative_chains.erase(ch_ent);
|
||||||
@ -847,8 +756,8 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//removing alt_chain entries from alternative chain
|
//removing alt_chain entries from alternative chains container
|
||||||
BOOST_FOREACH(auto ch_ent, alt_chain)
|
for (auto ch_ent : alt_chain)
|
||||||
{
|
{
|
||||||
m_alternative_chains.erase(ch_ent);
|
m_alternative_chains.erase(ch_ent);
|
||||||
}
|
}
|
||||||
@ -957,7 +866,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
|||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
//validate reward
|
//validate reward
|
||||||
uint64_t money_in_use = 0;
|
uint64_t money_in_use = 0;
|
||||||
BOOST_FOREACH(auto& o, b.miner_tx.vout)
|
for (auto& o : b.miner_tx.vout)
|
||||||
money_in_use += o.amount;
|
money_in_use += o.amount;
|
||||||
|
|
||||||
std::vector<size_t> last_blocks_sizes;
|
std::vector<size_t> last_blocks_sizes;
|
||||||
@ -992,8 +901,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// get the block sizes of the last <count> blocks, starting at <from_height>
|
// get the block sizes of the last <count> blocks, and return by reference <sz>.
|
||||||
// and return by reference <sz>.
|
|
||||||
void Blockchain::get_last_n_blocks_sizes(std::vector<size_t>& sz, size_t count) const
|
void Blockchain::get_last_n_blocks_sizes(std::vector<size_t>& sz, size_t count) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
@ -1061,7 +969,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|||||||
size_t real_txs_size = 0;
|
size_t real_txs_size = 0;
|
||||||
uint64_t real_fee = 0;
|
uint64_t real_fee = 0;
|
||||||
CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock);
|
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);
|
auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
|
||||||
if (cur_res == m_tx_pool.m_transactions.end())
|
if (cur_res == m_tx_pool.m_transactions.end())
|
||||||
@ -1103,10 +1011,13 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|||||||
#endif
|
#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
|
* two-phase miner transaction generation: we don't know exact block size
|
||||||
block size, so first miner transaction generated with fake amount of money, and with phase we know think we know expected 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, m_hardfork->get_current_version());
|
bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, 11, m_hardfork->get_current_version());
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance");
|
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);
|
size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx);
|
||||||
@ -1330,7 +1241,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");
|
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);
|
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)
|
if(is_a_checkpoint)
|
||||||
{
|
{
|
||||||
//do reorganize!
|
//do reorganize!
|
||||||
@ -1407,9 +1319,8 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list<block
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
//TODO: This function *looks* like it won't need to be rewritten
|
//FIXME: should we really be mixing missed block hashes with
|
||||||
// to use BlockchainDB, as it calls other functions that were,
|
// missed transaction hashes in the response?
|
||||||
// but it warrants some looking into later.
|
|
||||||
bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)
|
bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
@ -1418,28 +1329,47 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
|
|||||||
std::list<block> blocks;
|
std::list<block> blocks;
|
||||||
get_blocks(arg.blocks, blocks, rsp.missed_ids);
|
get_blocks(arg.blocks, blocks, rsp.missed_ids);
|
||||||
|
|
||||||
BOOST_FOREACH(const auto& bl, blocks)
|
for (const auto& bl : blocks)
|
||||||
{
|
{
|
||||||
std::list<crypto::hash> missed_tx_id;
|
std::list<crypto::hash> missed_tx_ids;
|
||||||
std::list<transaction> txs;
|
std::list<transaction> txs;
|
||||||
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()
|
get_transactions(bl.tx_hashes, txs, missed_tx_ids);
|
||||||
<< std::endl << "for block id = " << get_block_hash(bl));
|
|
||||||
|
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, see fixme above.
|
||||||
|
rsp.missed_ids.splice(rsp.missed_ids.end(), missed_tx_ids);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
rsp.blocks.push_back(block_complete_entry());
|
rsp.blocks.push_back(block_complete_entry());
|
||||||
block_complete_entry& e = rsp.blocks.back();
|
block_complete_entry& e = rsp.blocks.back();
|
||||||
//pack block
|
//pack block
|
||||||
e.block = t_serializable_object_to_blob(bl);
|
e.block = t_serializable_object_to_blob(bl);
|
||||||
//pack transactions
|
//pack transactions
|
||||||
BOOST_FOREACH(transaction& tx, txs)
|
for (transaction& tx : txs)
|
||||||
e.txs.push_back(t_serializable_object_to_blob(tx));
|
{
|
||||||
|
e.txs.push_back(t_serializable_object_to_blob(tx));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//get another transactions, if need
|
//get another transactions, if need
|
||||||
std::list<transaction> txs;
|
std::list<transaction> txs;
|
||||||
get_transactions(arg.txs, txs, rsp.missed_ids);
|
get_transactions(arg.txs, txs, rsp.missed_ids);
|
||||||
//pack aside transactions
|
//pack aside transactions
|
||||||
BOOST_FOREACH(const auto& tx, txs)
|
for (const auto& tx : txs)
|
||||||
rsp.txs.push_back(t_serializable_object_to_blob(tx));
|
{
|
||||||
|
rsp.txs.push_back(t_serializable_object_to_blob(tx));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1449,7 +1379,7 @@ bool Blockchain::get_alternative_blocks(std::list<block>& blocks) const
|
|||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
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);
|
blocks.push_back(alt_bl.second.bl);
|
||||||
}
|
}
|
||||||
@ -1640,6 +1570,8 @@ uint64_t Blockchain::block_difficulty(uint64_t i) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
//TODO: return type should be void, throw on exception
|
||||||
|
// alternatively, return true only if no blocks missed
|
||||||
template<class t_ids_container, class t_blocks_container, class t_missed_container>
|
template<class t_ids_container, class t_blocks_container, class t_missed_container>
|
||||||
bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const
|
bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const
|
||||||
{
|
{
|
||||||
@ -1664,6 +1596,8 @@ bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
//TODO: return type should be void, throw on exception
|
||||||
|
// alternatively, return true only if no transactions missed
|
||||||
template<class t_ids_container, class t_tx_container, class t_missed_container>
|
template<class t_ids_container, class t_tx_container, class t_missed_container>
|
||||||
bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const
|
bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const
|
||||||
{
|
{
|
||||||
@ -1680,7 +1614,6 @@ bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container
|
|||||||
{
|
{
|
||||||
missed_txs.push_back(tx_hash);
|
missed_txs.push_back(tx_hash);
|
||||||
}
|
}
|
||||||
//FIXME: is this the correct way to handle this?
|
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -1756,7 +1689,6 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
//FIXME: change argument to std::vector, low priority
|
|
||||||
// find split point between ours and foreign blockchain (or start at
|
// find split point between ours and foreign blockchain (or start at
|
||||||
// blockchain height <req_start_block>), and return up to max_count FULL
|
// blockchain height <req_start_block>), and return up to max_count FULL
|
||||||
// blocks by reference.
|
// blocks by reference.
|
||||||
@ -1937,6 +1869,11 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<u
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
//FIXME: it seems this function is meant to be merely a wrapper around
|
||||||
|
// another function of the same name, this one adding one bit of
|
||||||
|
// functionality. Should probably move anything more than that
|
||||||
|
// (getting the hash of the block at height max_used_block_id)
|
||||||
|
// to the other function to keep everything in one place.
|
||||||
// This function overloads its sister function with
|
// This function overloads its sister function with
|
||||||
// an extra value (hash of highest block that holds an output used as input)
|
// an extra value (hash of highest block that holds an output used as input)
|
||||||
// as a return-by-reference.
|
// as a return-by-reference.
|
||||||
@ -1945,6 +1882,8 @@ bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t& max_used_block
|
|||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
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)
|
#if defined(PER_BLOCK_CHECKPOINT)
|
||||||
// check if we're doing per-block checkpointing
|
// check if we're doing per-block checkpointing
|
||||||
if (m_db->height() < m_blocks_hash_check.size() && kept_by_block)
|
if (m_db->height() < m_blocks_hash_check.size() && kept_by_block)
|
||||||
@ -2000,7 +1939,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx)
|
|||||||
bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
|
bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
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);
|
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, in_to_key, true);
|
||||||
if(have_tx_keyimg_as_spent(in_to_key.k_image))
|
if(have_tx_keyimg_as_spent(in_to_key.k_image))
|
||||||
@ -2012,6 +1951,10 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
|
|||||||
// This function validates transaction inputs and their keys. Previously
|
// This function validates transaction inputs and their keys. Previously
|
||||||
// it also performed double spend checking, but that has been moved to its
|
// it also performed double spend checking, but that has been moved to its
|
||||||
// own function.
|
// 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)
|
bool Blockchain::check_tx_inputs(const transaction& tx, uint64_t* pmax_used_block_height)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
@ -2256,6 +2199,9 @@ bool Blockchain::check_tx_input(const txin_to_key& txin, const crypto::hash& tx_
|
|||||||
// 1. Disable locking and make method private.
|
// 1. Disable locking and make method private.
|
||||||
//CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
//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
|
struct outputs_visitor
|
||||||
{
|
{
|
||||||
std::vector<crypto::public_key >& m_output_keys;
|
std::vector<crypto::public_key >& m_output_keys;
|
||||||
@ -2280,7 +2226,7 @@ bool Blockchain::check_tx_input(const txin_to_key& txin, const crypto::hash& tx_
|
|||||||
|
|
||||||
output_keys.clear();
|
output_keys.clear();
|
||||||
|
|
||||||
//check ring signature
|
// collect output keys
|
||||||
outputs_visitor vi(output_keys, *this);
|
outputs_visitor vi(output_keys, *this);
|
||||||
if (!scan_outputkeys_for_indexes(txin, vi, tx_prefix_hash, pmax_related_block_height))
|
if (!scan_outputkeys_for_indexes(txin, vi, tx_prefix_hash, pmax_related_block_height))
|
||||||
{
|
{
|
||||||
@ -2415,8 +2361,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
|
// 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
|
// validation out of the next chunk of code to make sure that we correctly
|
||||||
// check PoW now.
|
// 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
|
// validate proof_of_work versus difficulty target
|
||||||
bool precomputed = false;
|
bool precomputed = false;
|
||||||
#if defined(PER_BLOCK_CHECKPOINT)
|
#if defined(PER_BLOCK_CHECKPOINT)
|
||||||
@ -2534,6 +2479,11 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
|
|||||||
txs.push_back(tx);
|
txs.push_back(tx);
|
||||||
TIME_MEASURE_START(dd);
|
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.
|
// ND: this is not needed, db->add_block() checks for duplicate k_images and fails accordingly.
|
||||||
// if (!check_for_double_spend(tx, keys))
|
// if (!check_for_double_spend(tx, keys))
|
||||||
// {
|
// {
|
||||||
@ -2555,7 +2505,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.");
|
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);
|
add_block_as_invalid(bl, id);
|
||||||
LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
||||||
bvc.m_verifivation_failed = true;
|
bvc.m_verifivation_failed = true;
|
||||||
@ -2712,6 +2662,8 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc
|
|||||||
return handle_block_to_main_chain(bl, id, 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)
|
void Blockchain::check_against_checkpoints(const checkpoints& points, bool enforce)
|
||||||
{
|
{
|
||||||
const auto& pts = points.get_points();
|
const auto& pts = points.get_points();
|
||||||
@ -2746,7 +2698,7 @@ void Blockchain::check_against_checkpoints(const checkpoints& points, bool enfor
|
|||||||
// with an existing checkpoint.
|
// with an existing checkpoint.
|
||||||
bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2755,7 +2707,7 @@ bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns
|
|||||||
// if we're not hard-enforcing dns checkpoints, handle accordingly
|
// if we're not hard-enforcing dns checkpoints, handle accordingly
|
||||||
if (m_enforce_dns_checkpoints && check_dns)
|
if (m_enforce_dns_checkpoints && check_dns)
|
||||||
{
|
{
|
||||||
if (!cryptonote::load_checkpoints_from_dns(m_checkpoints))
|
if (!m_checkpoints.load_checkpoints_from_dns())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2763,7 +2715,7 @@ bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns
|
|||||||
else if (check_dns)
|
else if (check_dns)
|
||||||
{
|
{
|
||||||
checkpoints dns_points;
|
checkpoints dns_points;
|
||||||
cryptonote::load_checkpoints_from_dns(dns_points);
|
dns_points.load_checkpoints_from_dns();
|
||||||
if (m_checkpoints.check_for_conflicts(dns_points))
|
if (m_checkpoints.check_for_conflicts(dns_points))
|
||||||
{
|
{
|
||||||
check_against_checkpoints(dns_points, false);
|
check_against_checkpoints(dns_points, false);
|
||||||
@ -2790,6 +2742,8 @@ void Blockchain::block_longhash_worker(const uint64_t height, const std::vector<
|
|||||||
TIME_MEASURE_START(t);
|
TIME_MEASURE_START(t);
|
||||||
slow_hash_allocate_state();
|
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)
|
for (const auto & block : blocks)
|
||||||
{
|
{
|
||||||
crypto::hash id = get_block_hash(block);
|
crypto::hash id = get_block_hash(block);
|
||||||
@ -2845,6 +2799,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<uint64_t> &offsets, std::vector<output_data_t> &outputs, std::unordered_map<crypto::hash, cryptonote::transaction> &txs) const
|
void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, std::unordered_map<crypto::hash, cryptonote::transaction> &txs) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -3195,3 +3150,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);
|
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<transaction> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -48,7 +48,7 @@
|
|||||||
#include "common/boost_serialization_helper.h"
|
#include "common/boost_serialization_helper.h"
|
||||||
#include "warnings.h"
|
#include "warnings.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
#include "cryptonote_core/checkpoints_create.h"
|
#include "cryptonote_core/checkpoints.h"
|
||||||
//#include "serialization/json_archive.h"
|
//#include "serialization/json_archive.h"
|
||||||
#include "../../contrib/otshell_utils/utils.hpp"
|
#include "../../contrib/otshell_utils/utils.hpp"
|
||||||
#include "../../src/p2p/data_logger.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.
|
// with an existing checkpoint.
|
||||||
bool blockchain_storage::update_checkpoints(const std::string& file_path, bool check_dns)
|
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;
|
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 we're not hard-enforcing dns checkpoints, handle accordingly
|
||||||
if (m_enforce_dns_checkpoints && check_dns)
|
if (m_enforce_dns_checkpoints && check_dns)
|
||||||
{
|
{
|
||||||
if (!cryptonote::load_checkpoints_from_dns(m_checkpoints))
|
if (!m_checkpoints.load_checkpoints_from_dns())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1870,7 +1870,7 @@ bool blockchain_storage::update_checkpoints(const std::string& file_path, bool c
|
|||||||
else if (check_dns)
|
else if (check_dns)
|
||||||
{
|
{
|
||||||
checkpoints dns_points;
|
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))
|
if (m_checkpoints.check_for_conflicts(dns_points))
|
||||||
{
|
{
|
||||||
check_against_checkpoints(dns_points, false);
|
check_against_checkpoints(dns_points, false);
|
||||||
|
@ -29,10 +29,40 @@
|
|||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
|
|
||||||
using namespace epee;
|
using namespace epee;
|
||||||
|
|
||||||
#include "checkpoints.h"
|
#include "checkpoints.h"
|
||||||
|
|
||||||
|
#include "common/dns_utils.h"
|
||||||
|
#include "include_base_utils.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& 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
|
namespace cryptonote
|
||||||
{
|
{
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@ -84,10 +114,7 @@ namespace cryptonote
|
|||||||
return check_block(height, h, ignored);
|
return check_block(height, h, ignored);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// this basically says if the blockchain is smaller than the first
|
//FIXME: is this the desired behavior?
|
||||||
// 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.
|
|
||||||
bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const
|
bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const
|
||||||
{
|
{
|
||||||
if (0 == block_height)
|
if (0 == block_height)
|
||||||
@ -128,4 +155,200 @@ namespace cryptonote
|
|||||||
}
|
}
|
||||||
return true;
|
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<t_hashline>::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<std::string> dns_urls = { "checkpoints.moneropulse.se"
|
||||||
|
, "checkpoints.moneropulse.org"
|
||||||
|
, "checkpoints.moneropulse.net"
|
||||||
|
, "checkpoints.moneropulse.co"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::vector<std::string> testnet_dns_urls = { "testpoints.moneropulse.se"
|
||||||
|
, "testpoints.moneropulse.org"
|
||||||
|
, "testpoints.moneropulse.net"
|
||||||
|
, "testpoints.moneropulse.co"
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::vector<std::string> > records;
|
||||||
|
records.resize(dns_urls.size());
|
||||||
|
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen(rd());
|
||||||
|
std::uniform_int_distribution<int> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,23 +32,186 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "cryptonote_basic_impl.h"
|
#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
|
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
|
class checkpoints
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief default constructor
|
||||||
|
*/
|
||||||
checkpoints();
|
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);
|
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 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;
|
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;
|
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;
|
uint64_t get_max_height() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief gets the checkpoints container
|
||||||
|
*
|
||||||
|
* @return a const reference to the checkpoints container
|
||||||
|
*/
|
||||||
const std::map<uint64_t, crypto::hash>& get_points() const;
|
const std::map<uint64_t, crypto::hash>& 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;
|
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:
|
private:
|
||||||
std::map<uint64_t, crypto::hash> m_points;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<t_hashline> hashlines; //!< the checkpoint lines from the file
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(hashlines)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<uint64_t, crypto::hash> m_points; //!< the checkpoints container
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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 <sstream>
|
|
||||||
#include <random>
|
|
||||||
#include "storages/portable_storage_template_helper.h" // epee json include
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& 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<t_hashline> 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<t_hashline>::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<std::string> dns_urls = { "checkpoints.moneropulse.se"
|
|
||||||
, "checkpoints.moneropulse.org"
|
|
||||||
, "checkpoints.moneropulse.net"
|
|
||||||
, "checkpoints.moneropulse.co"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::vector<std::string> testnet_dns_urls = { "testpoints.moneropulse.se"
|
|
||||||
, "testpoints.moneropulse.org"
|
|
||||||
, "testpoints.moneropulse.net"
|
|
||||||
, "testpoints.moneropulse.co"
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::vector<std::string> > records;
|
|
||||||
records.resize(dns_urls.size());
|
|
||||||
|
|
||||||
std::random_device rd;
|
|
||||||
std::mt19937 gen(rd());
|
|
||||||
std::uniform_int_distribution<int> 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
|
|
@ -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
|
|
@ -43,7 +43,7 @@ using namespace epee;
|
|||||||
#include "misc_language.h"
|
#include "misc_language.h"
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include "daemon/command_line_args.h"
|
#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/blockchain_db.h"
|
||||||
#include "blockchain_db/lmdb/db_lmdb.h"
|
#include "blockchain_db/lmdb/db_lmdb.h"
|
||||||
#if defined(BERKELEY_DB)
|
#if defined(BERKELEY_DB)
|
||||||
@ -146,7 +146,7 @@ namespace cryptonote
|
|||||||
if (!m_testnet)
|
if (!m_testnet)
|
||||||
{
|
{
|
||||||
cryptonote::checkpoints checkpoints;
|
cryptonote::checkpoints checkpoints;
|
||||||
if (!cryptonote::create_checkpoints(checkpoints))
|
if (!checkpoints.init_default_checkpoints())
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to initialize checkpoints");
|
throw std::runtime_error("Failed to initialize checkpoints");
|
||||||
}
|
}
|
||||||
@ -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.");
|
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);
|
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();
|
return load_state_data();
|
||||||
}
|
}
|
||||||
@ -556,11 +556,6 @@ namespace cryptonote
|
|||||||
return m_blockchain_storage.get_total_transactions();
|
return m_blockchain_storage.get_total_transactions();
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
//bool core::get_outs(uint64_t amount, std::list<crypto::public_key>& 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)
|
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))
|
if(m_mempool.have_tx(tx_hash))
|
||||||
@ -670,10 +665,6 @@ namespace cryptonote
|
|||||||
{
|
{
|
||||||
m_miner.on_synchronized();
|
m_miner.on_synchronized();
|
||||||
}
|
}
|
||||||
//bool core::get_backward_blocks_sizes(uint64_t from_height, std::vector<size_t>& 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)
|
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);
|
return m_blockchain_storage.get_block_by_hash(h, blk);
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
//void core::get_all_known_block_ids(std::list<crypto::hash> &main, std::list<crypto::hash> &alt, std::list<crypto::hash> &invalid) {
|
|
||||||
// m_blockchain_storage.get_all_known_block_ids(main, alt, invalid);
|
|
||||||
//}
|
|
||||||
//-----------------------------------------------------------------------------------------------
|
|
||||||
std::string core::print_pool(bool short_format) const
|
std::string core::print_pool(bool short_format) const
|
||||||
{
|
{
|
||||||
return m_mempool.print_pool(short_format);
|
return m_mempool.print_pool(short_format);
|
||||||
|
@ -55,152 +55,704 @@ DISABLE_VS_WARNINGS(4355)
|
|||||||
|
|
||||||
namespace cryptonote
|
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
|
class core: public i_miner_handler
|
||||||
{
|
{
|
||||||
public:
|
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);
|
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);
|
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();
|
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);
|
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);
|
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<block_complete_entry> &blocks);
|
bool prepare_handle_incoming_blocks(const std::list<block_complete_entry> &blocks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::cleanup_handle_incoming_blocks
|
||||||
|
*
|
||||||
|
* @note see Blockchain::cleanup_handle_incoming_blocks
|
||||||
|
*/
|
||||||
bool cleanup_handle_incoming_blocks(bool force_sync = false);
|
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;
|
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_cryptonote_protocol* get_protocol(){return m_pprotocol;}
|
||||||
|
|
||||||
//-------------------- i_miner_handler -----------------------
|
//-------------------- 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);
|
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);
|
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;}
|
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;}
|
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);
|
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);
|
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);
|
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();
|
bool deinit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sets fast exit flag
|
||||||
|
*
|
||||||
|
* @note see deinit()
|
||||||
|
*/
|
||||||
static void set_fast_exit();
|
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();
|
static bool get_fast_exit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sets to drop blocks downloaded (for testing)
|
||||||
|
*/
|
||||||
void test_drop_download();
|
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);
|
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;
|
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;
|
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;
|
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<block>&, std::list<transaction>&) const
|
||||||
|
*
|
||||||
|
* @note see Blockchain::get_blocks(uint64_t, size_t, std::list<block>&, std::list<transaction>&) const
|
||||||
|
*/
|
||||||
bool get_blocks(uint64_t start_offset, size_t count, std::list<block>& blocks, std::list<transaction>& txs) const;
|
bool get_blocks(uint64_t start_offset, size_t count, std::list<block>& blocks, std::list<transaction>& txs) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::get_blocks(uint64_t, size_t, std::list<block>&) const
|
||||||
|
*
|
||||||
|
* @note see Blockchain::get_blocks(uint64_t, size_t, std::list<block>&) const
|
||||||
|
*/
|
||||||
bool get_blocks(uint64_t start_offset, size_t count, std::list<block>& blocks) const;
|
bool get_blocks(uint64_t start_offset, size_t count, std::list<block>& 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<class t_ids_container, class t_blocks_container, class t_missed_container>
|
template<class t_ids_container, class t_blocks_container, class t_missed_container>
|
||||||
bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) const
|
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);
|
return m_blockchain_storage.get_blocks(block_ids, blocks, missed_bs);
|
||||||
}
|
}
|
||||||
crypto::hash get_block_id_by_height(uint64_t height) const;
|
|
||||||
bool get_transactions(const std::vector<crypto::hash>& txs_ids, std::list<transaction>& txs, std::list<crypto::hash>& missed_txs) const;
|
|
||||||
bool get_block_by_hash(const crypto::hash &h, block &blk) const;
|
|
||||||
//void get_all_known_block_ids(std::list<crypto::hash> &main, std::list<crypto::hash> &alt, std::list<crypto::hash> &invalid);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<crypto::hash>& txs_ids, std::list<transaction>& txs, std::list<crypto::hash>& 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::get_alternative_blocks
|
||||||
|
*
|
||||||
|
* @note see Blockchain::get_alternative_blocks(std::list<block>&) const
|
||||||
|
*/
|
||||||
bool get_alternative_blocks(std::list<block>& blocks) const;
|
bool get_alternative_blocks(std::list<block>& blocks) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::get_alternative_blocks_count
|
||||||
|
*
|
||||||
|
* @note see Blockchain::get_alternative_blocks_count() const
|
||||||
|
*/
|
||||||
size_t 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);
|
void set_cryptonote_protocol(i_cryptonote_protocol* pprotocol);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::set_checkpoints
|
||||||
|
*
|
||||||
|
* @note see Blockchain::set_checkpoints()
|
||||||
|
*/
|
||||||
void set_checkpoints(checkpoints&& chk_pts);
|
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);
|
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);
|
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<transaction>& txs) const;
|
bool get_pool_transactions(std::list<transaction>& 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_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const;
|
bool get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& 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;
|
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;
|
size_t get_blockchain_total_transactions() const;
|
||||||
//bool get_outs(uint64_t amount, std::list<crypto::public_key>& pkeys);
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::have_block
|
||||||
|
*
|
||||||
|
* @note see Blockchain::have_block
|
||||||
|
*/
|
||||||
bool have_block(const crypto::hash& id) const;
|
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<crypto::hash>& ids) const;
|
bool get_short_chain_history(std::list<crypto::hash>& ids) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::find_blockchain_supplement(const std::list<crypto::hash>&, NOTIFY_RESPONSE_CHAIN_ENTRY::request&) const
|
||||||
|
*
|
||||||
|
* @note see Blockchain::find_blockchain_supplement(const std::list<crypto::hash>&, NOTIFY_RESPONSE_CHAIN_ENTRY::request&) const
|
||||||
|
*/
|
||||||
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const;
|
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::find_blockchain_supplement(const uint64_t, const std::list<crypto::hash>&, std::list<std::pair<block, std::list<transaction> > >&, uint64_t&, uint64_t&, size_t) const
|
||||||
|
*
|
||||||
|
* @note see Blockchain::find_blockchain_supplement(const uint64_t, const std::list<crypto::hash>&, std::list<std::pair<block, std::list<transaction> > >&, uint64_t&, uint64_t&, size_t) const
|
||||||
|
*/
|
||||||
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const;
|
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& 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_stat_info(core_stat_info& st_inf) const;
|
||||||
//bool get_backward_blocks_sizes(uint64_t from_height, std::vector<size_t>& 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<uint64_t>& indexs) const;
|
bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::get_tail_id
|
||||||
|
*
|
||||||
|
* @note see Blockchain::get_tail_id
|
||||||
|
*/
|
||||||
crypto::hash get_tail_id() const;
|
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;
|
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();
|
void pause_mine();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc miner::resume
|
||||||
|
*
|
||||||
|
* @note see miner::resume
|
||||||
|
*/
|
||||||
void resume_mine();
|
void resume_mine();
|
||||||
|
|
||||||
#if BLOCKCHAIN_DB == DB_LMDB
|
#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;}
|
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;}
|
const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;}
|
||||||
#else
|
#else
|
||||||
blockchain_storage& get_blockchain_storage(){return m_blockchain_storage;}
|
blockchain_storage& get_blockchain_storage(){return m_blockchain_storage;}
|
||||||
const blockchain_storage& get_blockchain_storage()const{return m_blockchain_storage;}
|
const blockchain_storage& get_blockchain_storage()const{return m_blockchain_storage;}
|
||||||
#endif
|
#endif
|
||||||
//debug functions
|
|
||||||
|
/**
|
||||||
|
* @copydoc Blockchain::print_blockchain
|
||||||
|
*
|
||||||
|
* @note see Blockchain::print_blockchain
|
||||||
|
*/
|
||||||
void print_blockchain(uint64_t start_index, uint64_t end_index) const;
|
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;
|
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;
|
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);
|
void print_blockchain_outs(const std::string& file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc miner::on_synchronized
|
||||||
|
*
|
||||||
|
* @note see miner::on_synchronized
|
||||||
|
*/
|
||||||
void 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);
|
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;
|
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();
|
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();
|
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;
|
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<crypto::key_image>& key_im, std::vector<bool> &spent) const;
|
bool are_key_images_spent(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const;
|
||||||
|
|
||||||
private:
|
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);
|
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);
|
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);
|
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();
|
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;
|
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;
|
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;
|
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<crypto::signature>& 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();
|
bool update_miner_block_template();
|
||||||
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<bool> m_fast_exit;
|
|
||||||
bool m_test_drop_download = true;
|
|
||||||
uint64_t m_test_drop_download_height = 0;
|
|
||||||
|
|
||||||
tx_memory_pool m_mempool;
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<bool> 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
|
#if BLOCKCHAIN_DB == DB_LMDB
|
||||||
Blockchain m_blockchain_storage;
|
Blockchain m_blockchain_storage; //!< Blockchain instance
|
||||||
#else
|
#else
|
||||||
blockchain_storage m_blockchain_storage;
|
blockchain_storage m_blockchain_storage;
|
||||||
#endif
|
#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
|
//m_miner and m_miner_addres are probably temporary here
|
||||||
miner m_miner;
|
miner m_miner; //!< miner instance
|
||||||
account_public_address m_miner_address;
|
account_public_address m_miner_address; //!< address to mine to (for miner instance)
|
||||||
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<bool> m_starter_message_showed;
|
|
||||||
|
|
||||||
uint64_t m_target_blockchain_height;
|
std::string m_config_folder; //!< folder to look in for configs and other files
|
||||||
|
|
||||||
bool m_testnet;
|
cryptonote_protocol_stub m_protocol_stub; //!< cryptonote protocol stub instance
|
||||||
std::string m_checkpoints_path;
|
|
||||||
time_t m_last_dns_checkpoints_update;
|
|
||||||
time_t m_last_json_checkpoints_update;
|
|
||||||
|
|
||||||
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<bool> 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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,8 +116,8 @@ namespace cryptonote {
|
|||||||
return !carry;
|
return !carry;
|
||||||
}
|
}
|
||||||
|
|
||||||
difficulty_type next_difficulty(vector<uint64_t> timestamps, vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
|
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
|
||||||
//cutoff DIFFICULTY_LAG
|
|
||||||
if(timestamps.size() > DIFFICULTY_WINDOW)
|
if(timestamps.size() > DIFFICULTY_WINDOW)
|
||||||
{
|
{
|
||||||
timestamps.resize(DIFFICULTY_WINDOW);
|
timestamps.resize(DIFFICULTY_WINDOW);
|
||||||
@ -151,13 +151,15 @@ namespace cryptonote {
|
|||||||
assert(total_work > 0);
|
assert(total_work > 0);
|
||||||
uint64_t low, high;
|
uint64_t low, high;
|
||||||
mul(total_work, target_seconds, 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) {
|
if (high != 0 || low + time_span - 1 < low) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (low + time_span - 1) / time_span;
|
return (low + time_span - 1) / time_span;
|
||||||
}
|
}
|
||||||
|
|
||||||
difficulty_type next_difficulty(vector<uint64_t> timestamps, vector<difficulty_type> cumulative_difficulties)
|
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties)
|
||||||
{
|
{
|
||||||
return next_difficulty(std::move(timestamps), std::move(cumulative_difficulties), DIFFICULTY_TARGET);
|
return next_difficulty(std::move(timestamps), std::move(cumulative_difficulties), DIFFICULTY_TARGET);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,44 @@ namespace cryptonote
|
|||||||
{
|
{
|
||||||
typedef std::uint64_t difficulty_type;
|
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);
|
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<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties);
|
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload
|
||||||
|
*/
|
||||||
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cryptonote_core/checkpoints_create.h"
|
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
||||||
#include "misc_log_ex.h"
|
#include "misc_log_ex.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user