aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cryptonote_core/blockchain.cpp133
-rw-r--r--src/cryptonote_core/blockchain.h11
2 files changed, 88 insertions, 56 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 02f592b61..f18173ae8 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -270,7 +270,8 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain
m_db = db;
- if (testnet) {
+ m_testnet = testnet;
+ if (m_testnet) {
m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n)
m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
@@ -292,7 +293,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain
LOG_PRINT_L0("Blockchain not loaded, generating genesis block.");
block bl = boost::value_initialized<block>();
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);
}
@@ -330,45 +331,8 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain
m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
#if defined(PER_BLOCK_CHECKPOINT)
- if (!fakechain && m_fast_sync && get_blocks_dat_start(testnet) != nullptr)
- {
- if (get_blocks_dat_size(testnet) > 4)
- {
- const unsigned char *p = get_blocks_dat_start(testnet);
- const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
- const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
- if(nblocks > 0 && nblocks > m_db->height() && get_blocks_dat_size(testnet) >= size_needed)
- {
- 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;
- bool relayed;
- 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, relayed);
- }
- }
- }
- }
+ if (!fakechain)
+ load_compiled_in_block_hashes();
#endif
LOG_PRINT_GREEN("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block(), LOG_LEVEL_0);
@@ -652,10 +616,10 @@ void Blockchain::get_all_known_block_ids(std::list<crypto::hash> &main, std::lis
main.push_back(a);
}
- BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_alternative_chains)
+ for (const blocks_ext_by_hash::value_type &v: m_alternative_chains)
alt.push_back(v.first);
- BOOST_FOREACH(const blocks_ext_by_hash::value_type &v, m_invalid_blocks)
+ for (const blocks_ext_by_hash::value_type &v: m_invalid_blocks)
invalid.push_back(v.first);
}
//------------------------------------------------------------------
@@ -836,7 +800,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
}
//removing alt_chain entries from alternative chain
- BOOST_FOREACH(auto ch_ent, alt_chain)
+ for (auto ch_ent: alt_chain)
{
m_alternative_chains.erase(ch_ent);
}
@@ -948,7 +912,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
LOG_PRINT_L3("Blockchain::" << __func__);
//validate reward
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;
partial_block_reward = false;
@@ -1055,7 +1019,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
size_t real_txs_size = 0;
uint64_t real_fee = 0;
CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock);
- BOOST_FOREACH(crypto::hash &cur_hash, b.tx_hashes)
+ for(crypto::hash &cur_hash: b.tx_hashes)
{
auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
if (cur_res == m_tx_pool.m_transactions.end())
@@ -1409,26 +1373,40 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
std::list<block> blocks;
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;
- get_transactions(bl.tx_hashes, txs, rsp.missed_ids);
- CHECK_AND_ASSERT_MES(!missed_tx_id.size(), false, "Internal error: has missed missed_tx_id.size()=" << missed_tx_id.size()
- << std::endl << "for block id = " << get_block_hash(bl));
+ get_transactions(bl.tx_hashes, txs, missed_tx_ids);
+
+ if (missed_tx_ids.size() != 0)
+ {
+ LOG_ERROR("Error retrieving blocks, missed " << missed_tx_ids.size()
+ << " transactions for block with hash: " << get_block_hash(bl)
+ << std::endl
+ );
+ rsp.missed_ids.push_back(get_block_hash(bl));
+
+ // append missed transaction hashes to response missed_ids field,
+ // as done below if any standalone transactions were requested
+ // and missed.
+ rsp.missed_ids.splice(rsp.missed_ids.end(), missed_tx_ids);
+ return false;
+ }
+
rsp.blocks.push_back(block_complete_entry());
block_complete_entry& e = rsp.blocks.back();
//pack block
e.block = t_serializable_object_to_blob(bl);
//pack transactions
- BOOST_FOREACH(transaction& tx, txs)
+ for (transaction& tx: txs)
e.txs.push_back(t_serializable_object_to_blob(tx));
}
//get another transactions, if need
std::list<transaction> txs;
get_transactions(arg.txs, txs, rsp.missed_ids);
//pack aside transactions
- BOOST_FOREACH(const auto& tx, txs)
+ for (const auto& tx: txs)
rsp.txs.push_back(t_serializable_object_to_blob(tx));
return true;
@@ -1439,7 +1417,7 @@ bool Blockchain::get_alternative_blocks(std::list<block>& blocks) const
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
- BOOST_FOREACH(const auto& alt_bl, m_alternative_chains)
+ for (const auto& alt_bl: m_alternative_chains)
{
blocks.push_back(alt_bl.second.bl);
}
@@ -1988,7 +1966,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx)
// from hard fork 2, we forbid dust and compound outputs
if (m_hardfork->get_current_version() >= 2) {
- BOOST_FOREACH(auto &o, tx.vout) {
+ for (auto &o: tx.vout) {
if (!is_valid_decomposed_amount(o.amount)) {
return false;
}
@@ -2001,7 +1979,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx)
bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
- BOOST_FOREACH(const txin_v& in, tx.vin)
+ for (const txin_v& in: tx.vin)
{
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, in_to_key, true);
if(have_tx_keyimg_as_spent(in_to_key.k_image))
@@ -3249,6 +3227,49 @@ bool Blockchain::get_hard_fork_voting_info(uint8_t version, uint32_t &window, ui
return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);
}
+void Blockchain::load_compiled_in_block_hashes()
+{
+ if (m_fast_sync && get_blocks_dat_start(m_testnet) != nullptr)
+ {
+ if (get_blocks_dat_size(m_testnet) > 4)
+ {
+ const unsigned char *p = get_blocks_dat_start(m_testnet);
+ const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
+ const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
+ if(nblocks > 0 && nblocks > m_db->height() && get_blocks_dat_size(m_testnet) >= size_needed)
+ {
+ 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;
+ bool relayed;
+ 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, relayed);
+ }
+ }
+ }
+ }
+}
+
bool Blockchain::for_all_key_images(std::function<bool(const crypto::key_image&)> f) const
{
return m_db->for_all_key_images(f);
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index ecabf5376..89f623f90 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -239,6 +239,8 @@ namespace cryptonote
HardFork *m_hardfork;
+ bool m_testnet;
+
template<class visitor_t>
inline bool scan_outputkeys_for_indexes(const txin_to_key& tx_in_to_key, visitor_t &vis, const crypto::hash &tx_prefix_hash, uint64_t* pmax_related_block_height = NULL) const;
bool check_tx_input(const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, std::vector<crypto::public_key> &output_keys, uint64_t* pmax_related_block_height);
@@ -274,5 +276,14 @@ namespace cryptonote
void get_timestamp_and_difficulty(uint64_t &timestamp, difficulty_type &difficulty, const int offset) const;
void check_ring_signature(const crypto::hash &tx_prefix_hash, const crypto::key_image &key_image,
const std::vector<crypto::public_key> &pubkeys, const std::vector<crypto::signature> &sig, uint64_t &result);
+
+ /**
+ * @brief loads block hashes from compiled-in data set
+ *
+ * A (possibly empty) set of block hashes can be compiled into the
+ * monero daemon binary. This function loads those hashes into
+ * a useful state.
+ */
+ void load_compiled_in_block_hashes();
};
} // namespace cryptonote