mirror of
https://codeberg.org/anoncontributorxmr/monero.git
synced 2024-11-26 17:32:33 +00:00
Merge pull request #641
7658ac0
blockchain: revert handle_get_objects adding block id on tx not found (moneromooo-monero)3a0f4d8
berkeleydb: fix delete/free mismatch (moneromooo-monero)1642be2
minor bugfixes and refactoring (Thomas Winget)098dcf2
unit_tests: fix mnemonics unit test testing invalid seeds (moneromooo-monero)
This commit is contained in:
commit
cea6f6fb9c
4 changed files with 98 additions and 71 deletions
|
@ -925,12 +925,12 @@ void BlockchainBDB::open(const std::string& filename, const int db_flags)
|
||||||
// to zero (0) for reliability.
|
// to zero (0) for reliability.
|
||||||
m_blocks->stat(NULL, &stats, 0);
|
m_blocks->stat(NULL, &stats, 0);
|
||||||
m_height = stats->bt_nkeys;
|
m_height = stats->bt_nkeys;
|
||||||
delete stats;
|
free(stats);
|
||||||
|
|
||||||
// see above comment about DB_FAST_STAT
|
// see above comment about DB_FAST_STAT
|
||||||
m_output_indices->stat(NULL, &stats, 0);
|
m_output_indices->stat(NULL, &stats, 0);
|
||||||
m_num_outputs = stats->bt_nkeys;
|
m_num_outputs = stats->bt_nkeys;
|
||||||
delete stats;
|
free(stats);
|
||||||
|
|
||||||
// checks for compatibility
|
// checks for compatibility
|
||||||
bool compatible = true;
|
bool compatible = true;
|
||||||
|
|
|
@ -270,7 +270,8 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const bool fakechain
|
||||||
|
|
||||||
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_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
|
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.");
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
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 (!fakechain && m_fast_sync && get_blocks_dat_start(testnet) != nullptr)
|
if (!fakechain)
|
||||||
{
|
load_compiled_in_block_hashes();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#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);
|
||||||
|
@ -652,10 +616,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);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -836,7 +800,7 @@ 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 chain
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -948,7 +912,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;
|
||||||
partial_block_reward = false;
|
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;
|
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())
|
||||||
|
@ -1409,26 +1373,39 @@ 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);
|
get_transactions(bl.tx_hashes, txs, missed_tx_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));
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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());
|
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;
|
||||||
|
@ -1439,7 +1416,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);
|
||||||
}
|
}
|
||||||
|
@ -1988,7 +1965,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx)
|
||||||
|
|
||||||
// from hard fork 2, we forbid dust and compound outputs
|
// from hard fork 2, we forbid dust and compound outputs
|
||||||
if (m_hardfork->get_current_version() >= 2) {
|
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)) {
|
if (!is_valid_decomposed_amount(o.amount)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2001,7 +1978,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))
|
||||||
|
@ -3249,6 +3226,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);
|
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
|
bool Blockchain::for_all_key_images(std::function<bool(const crypto::key_image&)> f) const
|
||||||
{
|
{
|
||||||
return m_db->for_all_key_images(f);
|
return m_db->for_all_key_images(f);
|
||||||
|
|
|
@ -239,6 +239,8 @@ namespace cryptonote
|
||||||
|
|
||||||
HardFork *m_hardfork;
|
HardFork *m_hardfork;
|
||||||
|
|
||||||
|
bool m_testnet;
|
||||||
|
|
||||||
template<class visitor_t>
|
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;
|
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);
|
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 ×tamp, difficulty_type &difficulty, const int offset) const;
|
void get_timestamp_and_difficulty(uint64_t ×tamp, difficulty_type &difficulty, const int offset) const;
|
||||||
void check_ring_signature(const crypto::hash &tx_prefix_hash, const crypto::key_image &key_image,
|
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);
|
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
|
} // namespace cryptonote
|
||||||
|
|
|
@ -44,16 +44,6 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/*!
|
|
||||||
* \brief Returns random index from 0 to max-1
|
|
||||||
* \param max Range maximum
|
|
||||||
* \return required random index
|
|
||||||
*/
|
|
||||||
uint32_t get_random_index(int max)
|
|
||||||
{
|
|
||||||
return rand() % max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Compares vectors for equality
|
* \brief Compares vectors for equality
|
||||||
* \param expected expected vector
|
* \param expected expected vector
|
||||||
|
@ -78,11 +68,17 @@ namespace
|
||||||
const std::vector<std::string> &word_list = language.get_word_list();
|
const std::vector<std::string> &word_list = language.get_word_list();
|
||||||
std::string seed = "", return_seed = "";
|
std::string seed = "", return_seed = "";
|
||||||
// Generate a random seed without checksum
|
// Generate a random seed without checksum
|
||||||
for (int ii = 0; ii < crypto::ElectrumWords::seed_length; ii++)
|
crypto::secret_key randkey;
|
||||||
|
for (size_t ii = 0; ii < sizeof(randkey); ++ii)
|
||||||
{
|
{
|
||||||
seed += (word_list[get_random_index(word_list.size())] + ' ');
|
randkey.data[ii] = rand();
|
||||||
}
|
}
|
||||||
seed.pop_back();
|
crypto::ElectrumWords::bytes_to_words(randkey, seed, language.get_language_name());
|
||||||
|
// remove the checksum word
|
||||||
|
const char *space = strrchr(seed.c_str(), ' ');
|
||||||
|
ASSERT_TRUE(space != NULL);
|
||||||
|
seed = std::string(seed.c_str(), space-seed.c_str());
|
||||||
|
|
||||||
std::cout << "Test seed without checksum:\n";
|
std::cout << "Test seed without checksum:\n";
|
||||||
std::cout << seed << std::endl;
|
std::cout << seed << std::endl;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue