Merge pull request #6111
d20ff4f64
functional_tests: add a large (many randomx epochs) p2p reorg test (moneromooo-monero)6a0b3b1f8
functional_tests: add randomx tests (moneromooo-monero)9d42649d5
core: fix mining from a block that's not the current top (moneromooo-monero)
This commit is contained in:
commit
aefa7740c3
|
@ -116,6 +116,46 @@ static inline int enabled_flags(void) {
|
|||
#define SEEDHASH_EPOCH_BLOCKS 2048 /* Must be same as BLOCKS_SYNCHRONIZING_MAX_COUNT in cryptonote_config.h */
|
||||
#define SEEDHASH_EPOCH_LAG 64
|
||||
|
||||
static inline int is_power_of_2(uint64_t n) { return n && (n & (n-1)) == 0; }
|
||||
|
||||
static int get_seedhash_epoch_lag(void)
|
||||
{
|
||||
static unsigned int lag = (unsigned int)-1;
|
||||
if (lag != (unsigned int)-1)
|
||||
return lag;
|
||||
const char *e = getenv("SEEDHASH_EPOCH_LAG");
|
||||
if (e)
|
||||
{
|
||||
lag = atoi(e);
|
||||
if (lag > SEEDHASH_EPOCH_LAG || !is_power_of_2(lag))
|
||||
lag = SEEDHASH_EPOCH_LAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
lag = SEEDHASH_EPOCH_LAG;
|
||||
}
|
||||
return lag;
|
||||
}
|
||||
|
||||
static unsigned int get_seedhash_epoch_blocks(void)
|
||||
{
|
||||
static unsigned int blocks = (unsigned int)-1;
|
||||
if (blocks != (unsigned int)-1)
|
||||
return blocks;
|
||||
const char *e = getenv("SEEDHASH_EPOCH_BLOCKS");
|
||||
if (e)
|
||||
{
|
||||
blocks = atoi(e);
|
||||
if (blocks < 2 || blocks > SEEDHASH_EPOCH_BLOCKS || !is_power_of_2(blocks))
|
||||
blocks = SEEDHASH_EPOCH_BLOCKS;
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks = SEEDHASH_EPOCH_BLOCKS;
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
void rx_reorg(const uint64_t split_height) {
|
||||
int i;
|
||||
CTHR_MUTEX_LOCK(rx_mutex);
|
||||
|
@ -130,14 +170,16 @@ void rx_reorg(const uint64_t split_height) {
|
|||
}
|
||||
|
||||
uint64_t rx_seedheight(const uint64_t height) {
|
||||
uint64_t s_height = (height <= SEEDHASH_EPOCH_BLOCKS+SEEDHASH_EPOCH_LAG) ? 0 :
|
||||
(height - SEEDHASH_EPOCH_LAG - 1) & ~(SEEDHASH_EPOCH_BLOCKS-1);
|
||||
const uint64_t seedhash_epoch_lag = get_seedhash_epoch_lag();
|
||||
const uint64_t seedhash_epoch_blocks = get_seedhash_epoch_blocks();
|
||||
uint64_t s_height = (height <= seedhash_epoch_blocks+seedhash_epoch_lag) ? 0 :
|
||||
(height - seedhash_epoch_lag - 1) & ~(seedhash_epoch_blocks-1);
|
||||
return s_height;
|
||||
}
|
||||
|
||||
void rx_seedheights(const uint64_t height, uint64_t *seedheight, uint64_t *nextheight) {
|
||||
*seedheight = rx_seedheight(height);
|
||||
*nextheight = rx_seedheight(height + SEEDHASH_EPOCH_LAG);
|
||||
*nextheight = rx_seedheight(height + get_seedhash_epoch_lag());
|
||||
}
|
||||
|
||||
typedef struct seedinfo {
|
||||
|
@ -194,7 +236,7 @@ static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_
|
|||
void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length,
|
||||
char *hash, int miners, int is_alt) {
|
||||
uint64_t s_height = rx_seedheight(mainheight);
|
||||
int toggle = (s_height & SEEDHASH_EPOCH_BLOCKS) != 0;
|
||||
int toggle = (s_height & get_seedhash_epoch_blocks()) != 0;
|
||||
randomx_flags flags = enabled_flags() & ~disabled_flags();
|
||||
rx_state *rx_sp;
|
||||
randomx_cache *cache;
|
||||
|
|
|
@ -169,7 +169,9 @@ namespace cryptonote
|
|||
extra_nonce = m_extra_messages[m_config.current_extra_message_index];
|
||||
}
|
||||
|
||||
if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce))
|
||||
uint64_t seed_height;
|
||||
crypto::hash seed_hash;
|
||||
if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce, seed_height, seed_hash))
|
||||
{
|
||||
LOG_ERROR("Failed to get_block_template(), stopping mining");
|
||||
return false;
|
||||
|
@ -471,12 +473,12 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
bool miner::find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height)
|
||||
bool miner::find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height, const crypto::hash *seed_hash)
|
||||
{
|
||||
for(; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++)
|
||||
{
|
||||
crypto::hash h;
|
||||
gbh(bl, height, diffic <= 100 ? 0 : tools::get_max_concurrency(), h);
|
||||
gbh(bl, height, seed_hash, diffic <= 100 ? 0 : tools::get_max_concurrency(), h);
|
||||
|
||||
if(check_hash(h, diffic))
|
||||
{
|
||||
|
@ -572,7 +574,7 @@ namespace cryptonote
|
|||
|
||||
b.nonce = nonce;
|
||||
crypto::hash h;
|
||||
m_gbh(b, height, tools::get_max_concurrency(), h);
|
||||
m_gbh(b, height, NULL, tools::get_max_concurrency(), h);
|
||||
|
||||
if(check_hash(h, local_diff))
|
||||
{
|
||||
|
|
|
@ -47,12 +47,12 @@ namespace cryptonote
|
|||
struct i_miner_handler
|
||||
{
|
||||
virtual bool handle_block_found(block& b, block_verification_context &bvc) = 0;
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce) = 0;
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash) = 0;
|
||||
protected:
|
||||
~i_miner_handler(){};
|
||||
};
|
||||
|
||||
typedef std::function<bool(const cryptonote::block&, uint64_t, unsigned int, crypto::hash&)> get_block_hash_t;
|
||||
typedef std::function<bool(const cryptonote::block&, uint64_t, const crypto::hash*, unsigned int, crypto::hash&)> get_block_hash_t;
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
|
@ -76,7 +76,7 @@ namespace cryptonote
|
|||
bool on_idle();
|
||||
void on_synchronized();
|
||||
//synchronous analog (for fast calls)
|
||||
static bool find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height);
|
||||
static bool find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height, const crypto::hash *seed_hash = NULL);
|
||||
void pause();
|
||||
void resume();
|
||||
void do_print_hashrate(bool do_hr);
|
||||
|
|
|
@ -1506,13 +1506,15 @@ uint64_t Blockchain::get_current_cumulative_block_weight_median() const
|
|||
// in a lot of places. That flag is not referenced in any of the code
|
||||
// nor any of the makefiles, howeve. Need to look into whether or not it's
|
||||
// necessary at all.
|
||||
bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
size_t median_weight;
|
||||
uint64_t already_generated_coins;
|
||||
uint64_t pool_cookie;
|
||||
|
||||
seed_hash = crypto::null_hash;
|
||||
|
||||
m_tx_pool.lock();
|
||||
const auto unlock_guard = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); });
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
|
@ -1531,6 +1533,8 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
|||
diffic = m_btc_difficulty;
|
||||
height = m_btc_height;
|
||||
expected_reward = m_btc_expected_reward;
|
||||
seed_height = m_btc_seed_height;
|
||||
seed_hash = m_btc_seed_hash;
|
||||
return true;
|
||||
}
|
||||
MDEBUG("Not using cached template: address " << (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address))) << ", nonce " << (m_btc_nonce == ex_nonce) << ", cookie " << (m_btc_pool_cookie == m_tx_pool.cookie()) << ", from_block " << (!!from_block));
|
||||
|
@ -1564,10 +1568,34 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
|||
CHECK_AND_ASSERT_MES(get_block_by_hash(*from_block, prev_block), false, "From block not found"); // TODO
|
||||
uint64_t from_block_height = cryptonote::get_block_height(prev_block);
|
||||
height = from_block_height + 1;
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
height = alt_chain.back().height + 1;
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
|
||||
if (alt_chain.size() && alt_chain.front().height <= seed_height)
|
||||
{
|
||||
for (auto it=alt_chain.begin(); it != alt_chain.end(); it++)
|
||||
{
|
||||
if (it->height == seed_height+1)
|
||||
{
|
||||
seed_hash = it->bl.prev_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
}
|
||||
b.major_version = m_hardfork->get_ideal_version(height);
|
||||
b.minor_version = m_hardfork->get_ideal_version();
|
||||
|
@ -1602,6 +1630,12 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
|||
median_weight = m_current_block_cumul_weight_limit / 2;
|
||||
diffic = get_difficulty_for_next_block();
|
||||
already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
}
|
||||
b.timestamp = time(NULL);
|
||||
|
||||
|
@ -1734,16 +1768,16 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
|||
#endif
|
||||
|
||||
if (!from_block)
|
||||
cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, pool_cookie);
|
||||
cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, seed_height, seed_hash, pool_cookie);
|
||||
return true;
|
||||
}
|
||||
LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::create_block_template(block& b, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool Blockchain::create_block_template(block& b, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
return create_block_template(b, NULL, miner_address, diffic, height, expected_reward, ex_nonce);
|
||||
return create_block_template(b, NULL, miner_address, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
// for an alternate chain, get the timestamps from the main chain to complete
|
||||
|
@ -5443,7 +5477,7 @@ void Blockchain::invalidate_block_template_cache()
|
|||
m_btc_valid = false;
|
||||
}
|
||||
|
||||
void Blockchain::cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t pool_cookie)
|
||||
void Blockchain::cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t seed_height, const crypto::hash &seed_hash, uint64_t pool_cookie)
|
||||
{
|
||||
MDEBUG("Setting block template cache");
|
||||
m_btc = b;
|
||||
|
@ -5452,6 +5486,8 @@ void Blockchain::cache_block_template(const block &b, const cryptonote::account_
|
|||
m_btc_difficulty = diff;
|
||||
m_btc_height = height;
|
||||
m_btc_expected_reward = expected_reward;
|
||||
m_btc_seed_hash = seed_hash;
|
||||
m_btc_seed_height = seed_height;
|
||||
m_btc_pool_cookie = pool_cookie;
|
||||
m_btc_valid = true;
|
||||
}
|
||||
|
|
|
@ -366,8 +366,8 @@ namespace cryptonote
|
|||
*
|
||||
* @return true if block template filled in successfully, else false
|
||||
*/
|
||||
bool create_block_template(block& b, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
bool create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
bool create_block_template(block& b, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
bool create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
|
||||
/**
|
||||
* @brief checks if a block is known about with a given hash
|
||||
|
@ -1124,6 +1124,8 @@ namespace cryptonote
|
|||
uint64_t m_btc_height;
|
||||
uint64_t m_btc_pool_cookie;
|
||||
uint64_t m_btc_expected_reward;
|
||||
crypto::hash m_btc_seed_hash;
|
||||
uint64_t m_btc_seed_height;
|
||||
bool m_btc_valid;
|
||||
|
||||
|
||||
|
@ -1520,6 +1522,6 @@ namespace cryptonote
|
|||
*
|
||||
* At some point, may be used to push an update to miners
|
||||
*/
|
||||
void cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t pool_cookie);
|
||||
void cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t seed_height, const crypto::hash &seed_hash, uint64_t pool_cookie);
|
||||
};
|
||||
} // namespace cryptonote
|
||||
|
|
|
@ -226,8 +226,8 @@ namespace cryptonote
|
|||
core::core(i_cryptonote_protocol* pprotocol):
|
||||
m_mempool(m_blockchain_storage),
|
||||
m_blockchain_storage(m_mempool),
|
||||
m_miner(this, [this](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&m_blockchain_storage, b, hash, height, threads);
|
||||
m_miner(this, [this](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&m_blockchain_storage, b, hash, height, seed_hash, threads);
|
||||
}),
|
||||
m_starter_message_showed(false),
|
||||
m_target_blockchain_height(0),
|
||||
|
@ -1184,11 +1184,42 @@ namespace cryptonote
|
|||
size_t core::get_block_sync_size(uint64_t height) const
|
||||
{
|
||||
static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0;
|
||||
size_t res = 0;
|
||||
if (block_sync_size > 0)
|
||||
return block_sync_size;
|
||||
if (height >= quick_height)
|
||||
return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
|
||||
return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4;
|
||||
res = block_sync_size;
|
||||
else if (height >= quick_height)
|
||||
res = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
|
||||
else
|
||||
res = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4;
|
||||
|
||||
static size_t max_block_size = 0;
|
||||
if (max_block_size == 0)
|
||||
{
|
||||
const char *env = getenv("SEEDHASH_EPOCH_BLOCKS");
|
||||
if (env)
|
||||
{
|
||||
int n = atoi(env);
|
||||
if (n <= 0)
|
||||
n = BLOCKS_SYNCHRONIZING_MAX_COUNT;
|
||||
size_t p = 1;
|
||||
while (p < (size_t)n)
|
||||
p <<= 1;
|
||||
max_block_size = p;
|
||||
}
|
||||
else
|
||||
max_block_size = BLOCKS_SYNCHRONIZING_MAX_COUNT;
|
||||
}
|
||||
if (res > max_block_size)
|
||||
{
|
||||
static bool warned = false;
|
||||
if (!warned)
|
||||
{
|
||||
MWARNING("Clamping block sync size to " << max_block_size);
|
||||
warned = true;
|
||||
}
|
||||
res = max_block_size;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::are_key_images_spent_in_pool(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
|
||||
|
@ -1360,14 +1391,14 @@ namespace cryptonote
|
|||
m_mempool.set_relayed(epee::to_span(tx_hashes), tx_relay);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce);
|
||||
return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce);
|
||||
return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, bool clip_pruned, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
|
||||
|
|
|
@ -231,8 +231,8 @@ namespace cryptonote
|
|||
*
|
||||
* @note see Blockchain::create_block_template
|
||||
*/
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
virtual bool get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
virtual bool get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
|
||||
/**
|
||||
* @brief called when a transaction is relayed.
|
||||
|
|
|
@ -663,9 +663,9 @@ namespace cryptonote
|
|||
bl.minor_version = CURRENT_BLOCK_MINOR_VERSION;
|
||||
bl.timestamp = 0;
|
||||
bl.nonce = nonce;
|
||||
miner::find_nonce_for_given_block([](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(NULL, b, hash, height, threads);
|
||||
}, bl, 1, 0);
|
||||
miner::find_nonce_for_given_block([](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(NULL, b, hash, height, seed_hash, threads);
|
||||
}, bl, 1, 0, NULL);
|
||||
bl.invalidate_hashes();
|
||||
return true;
|
||||
}
|
||||
|
@ -676,7 +676,7 @@ namespace cryptonote
|
|||
rx_slow_hash(main_height, seed_height, seed_hash.data, bd.data(), bd.size(), res.data, 0, 1);
|
||||
}
|
||||
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const int miners)
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash, const int miners)
|
||||
{
|
||||
// block 202612 bug workaround
|
||||
if (height == 202612)
|
||||
|
@ -693,7 +693,7 @@ namespace cryptonote
|
|||
if (pbc != NULL)
|
||||
{
|
||||
seed_height = rx_seedheight(height);
|
||||
hash = pbc->get_pending_block_id_by_height(seed_height);
|
||||
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
|
||||
main_height = pbc->get_current_blockchain_height();
|
||||
} else
|
||||
{
|
||||
|
@ -701,7 +701,7 @@ namespace cryptonote
|
|||
seed_height = 0;
|
||||
main_height = 0;
|
||||
}
|
||||
rx_slow_hash(main_height, seed_height, hash.data, bd.data(), bd.size(), res.data, miners, 0);
|
||||
rx_slow_hash(main_height, seed_height, hash.data, bd.data(), bd.size(), res.data, seed_hash ? 0 : miners, !!seed_hash);
|
||||
} else {
|
||||
const int pow_variant = b.major_version >= 7 ? b.major_version - 6 : 0;
|
||||
crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height);
|
||||
|
@ -709,6 +709,11 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const int miners)
|
||||
{
|
||||
return get_block_longhash(pbc, b, res, height, NULL, miners);
|
||||
}
|
||||
|
||||
crypto::hash get_block_longhash(const Blockchain *pbc, const block& b, const uint64_t height, const int miners)
|
||||
{
|
||||
crypto::hash p = crypto::null_hash;
|
||||
|
|
|
@ -134,6 +134,7 @@ namespace cryptonote
|
|||
|
||||
class Blockchain;
|
||||
bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const int miners);
|
||||
bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash, const int miners);
|
||||
void get_altblock_longhash(const block& b, crypto::hash& res, const uint64_t main_height, const uint64_t height,
|
||||
const uint64_t seed_height, const crypto::hash& seed_hash);
|
||||
crypto::hash get_block_longhash(const Blockchain *pb, const block& b, const uint64_t height, const int miners);
|
||||
|
|
|
@ -1642,7 +1642,7 @@ namespace cryptonote
|
|||
bool core_rpc_server::get_block_template(const account_public_address &address, const crypto::hash *prev_block, const cryptonote::blobdata &extra_nonce, size_t &reserved_offset, cryptonote::difficulty_type &difficulty, uint64_t &height, uint64_t &expected_reward, block &b, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, epee::json_rpc::error &error_resp)
|
||||
{
|
||||
b = boost::value_initialized<cryptonote::block>();
|
||||
if(!m_core.get_block_template(b, prev_block, address, difficulty, height, expected_reward, extra_nonce))
|
||||
if(!m_core.get_block_template(b, prev_block, address, difficulty, height, expected_reward, extra_nonce, seed_height, seed_hash))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Internal error: failed to create block template";
|
||||
|
@ -1659,17 +1659,6 @@ namespace cryptonote
|
|||
return false;
|
||||
}
|
||||
|
||||
if (b.major_version >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = m_core.get_block_id_by_height(seed_height);
|
||||
if (next_height != seed_height)
|
||||
next_seed_hash = m_core.get_block_id_by_height(next_height);
|
||||
else
|
||||
next_seed_hash = seed_hash;
|
||||
}
|
||||
|
||||
if (extra_nonce.empty())
|
||||
{
|
||||
reserved_offset = 0;
|
||||
|
@ -1897,9 +1886,16 @@ namespace cryptonote
|
|||
return false;
|
||||
}
|
||||
b.nonce = req.starting_nonce;
|
||||
miner::find_nonce_for_given_block([this](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&(m_core.get_blockchain_storage()), b, hash, height, threads);
|
||||
}, b, template_res.difficulty, template_res.height);
|
||||
crypto::hash seed_hash = crypto::null_hash;
|
||||
if (b.major_version >= RX_BLOCK_VERSION && !epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error converting seed hash";
|
||||
return false;
|
||||
}
|
||||
miner::find_nonce_for_given_block([this](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&(m_core.get_blockchain_storage()), b, hash, height, seed_hash, threads);
|
||||
}, b, template_res.difficulty, template_res.height, &seed_hash);
|
||||
|
||||
submit_req.front() = string_tools::buff_to_hex_nodelimer(block_to_blob(b));
|
||||
r = on_submitblock(submit_req, submit_res, error_resp, ctx);
|
||||
|
|
|
@ -409,9 +409,9 @@ void test_generator::fill_nonce(cryptonote::block& blk, const difficulty_type& d
|
|||
}
|
||||
|
||||
blk.nonce = 0;
|
||||
while (!miner::find_nonce_for_given_block([blockchain](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(blockchain, b, hash, height, threads);
|
||||
}, blk, diffic, height)) {
|
||||
while (!miner::find_nonce_for_given_block([blockchain](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(blockchain, b, hash, height, seed_hash, threads);
|
||||
}, blk, diffic, height, NULL)) {
|
||||
blk.timestamp++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,9 @@ try:
|
|||
os.environ['PYTHONIOENCODING'] = 'utf-8'
|
||||
os.environ['DIFFICULTY'] = str(DIFFICULTY)
|
||||
os.environ['MAKE_TEST_SIGNATURE'] = builddir + '/tests/functional_tests/make_test_signature'
|
||||
os.environ['SEEDHASH_EPOCH_BLOCKS'] = "8"
|
||||
os.environ['SEEDHASH_EPOCH_LAG'] = "4"
|
||||
|
||||
for i in range(len(command_lines)):
|
||||
#print('Running: ' + str(command_lines[i]))
|
||||
processes.append(subprocess.Popen(command_lines[i], stdout = outputs[i]))
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import os
|
||||
|
||||
"""Test daemon mining RPC calls
|
||||
|
||||
|
@ -49,6 +50,8 @@ class MiningTest():
|
|||
self.mine(True)
|
||||
self.mine(False)
|
||||
self.submitblock()
|
||||
self.reset()
|
||||
self.test_randomx()
|
||||
|
||||
def reset(self):
|
||||
print('Resetting blockchain')
|
||||
|
@ -169,6 +172,117 @@ class MiningTest():
|
|||
assert res.height == height + i + 1
|
||||
assert res.hash == block_hash
|
||||
|
||||
def test_randomx(self):
|
||||
print("Test RandomX")
|
||||
|
||||
daemon = Daemon()
|
||||
wallet = Wallet()
|
||||
|
||||
res = daemon.get_height()
|
||||
daemon.pop_blocks(res.height - 1)
|
||||
daemon.flush_txpool()
|
||||
|
||||
epoch = int(os.environ['SEEDHASH_EPOCH_BLOCKS'])
|
||||
lag = int(os.environ['SEEDHASH_EPOCH_LAG'])
|
||||
address = '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
|
||||
|
||||
# check we can generate blocks, and that the seed hash changes when expected
|
||||
res = daemon.getblocktemplate(address)
|
||||
first_seed_hash = res.seed_hash
|
||||
daemon.generateblocks(address, 1 + lag)
|
||||
res = daemon.mining_status()
|
||||
assert res.active == False
|
||||
assert res.pow_algorithm == 'RandomX'
|
||||
res = daemon.getblocktemplate(address)
|
||||
seed_hash = res.seed_hash
|
||||
t0 = time.time()
|
||||
daemon.generateblocks(address, epoch - 3)
|
||||
t0 = time.time() - t0
|
||||
res = daemon.get_info()
|
||||
assert res.height == lag + epoch - 1
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert seed_hash == res.seed_hash
|
||||
t0 = time.time()
|
||||
daemon.generateblocks(address, 1)
|
||||
t0 = time.time() - t0
|
||||
res = daemon.get_info()
|
||||
assert res.height == lag + epoch
|
||||
daemon.generateblocks(address, 1)
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert seed_hash != res.seed_hash
|
||||
new_seed_hash = res.seed_hash
|
||||
t0 = time.time()
|
||||
daemon.generateblocks(address, epoch - 1)
|
||||
t0 = time.time() - t0
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert new_seed_hash == res.seed_hash
|
||||
daemon.generateblocks(address, 1)
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert new_seed_hash != res.seed_hash
|
||||
new_seed_hash = res.seed_hash
|
||||
t0 = time.time()
|
||||
daemon.generateblocks(address, epoch - 1)
|
||||
t0 = time.time() - t0
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert new_seed_hash == res.seed_hash
|
||||
daemon.generateblocks(address, 1)
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert new_seed_hash != res.seed_hash
|
||||
#print('First mining: ' + str(t0))
|
||||
|
||||
# pop all these blocks, and feed them again to monerod
|
||||
print('Recreating the chain')
|
||||
res = daemon.get_info()
|
||||
height = res.height
|
||||
assert height == lag + epoch * 3 + 1
|
||||
block_hashes = [x.hash for x in daemon.getblockheadersrange(0, height - 1).headers]
|
||||
assert len(block_hashes) == height
|
||||
blocks = []
|
||||
for i in range(len(block_hashes)):
|
||||
res = daemon.getblock(height = i)
|
||||
assert res.block_header.hash == block_hashes[i]
|
||||
blocks.append(res.blob)
|
||||
daemon.pop_blocks(height)
|
||||
res = daemon.get_info()
|
||||
assert res.height == 1
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert first_seed_hash == res.seed_hash
|
||||
t0 = time.time()
|
||||
for h in range(len(block_hashes)):
|
||||
res = daemon.submitblock(blocks[h])
|
||||
t0 = time.time() - t0
|
||||
res = daemon.get_info()
|
||||
assert height == res.height
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert new_seed_hash != res.seed_hash
|
||||
res = daemon.pop_blocks(1)
|
||||
res = daemon.getblocktemplate(address)
|
||||
assert new_seed_hash == res.seed_hash
|
||||
#print('Submit: ' + str(t0))
|
||||
|
||||
# start mining from the genesis block again
|
||||
print('Mining from genesis block again')
|
||||
res = daemon.get_height()
|
||||
top_hash = res.hash
|
||||
res = daemon.getblockheaderbyheight(0)
|
||||
genesis_block_hash = res.block_header.hash
|
||||
t0 = time.time()
|
||||
daemon.generateblocks(address, height - 2, prev_block = genesis_block_hash)
|
||||
t0 = time.time() - t0
|
||||
res = daemon.get_info()
|
||||
assert res.height == height - 1
|
||||
assert res.top_block_hash == top_hash
|
||||
#print('Second mining: ' + str(t0))
|
||||
|
||||
# that one will cause a huge reorg
|
||||
print('Adding one to reorg')
|
||||
res = daemon.generateblocks(address, 1)
|
||||
assert len(res.blocks) == 1
|
||||
new_top_hash = res.blocks[0]
|
||||
res = daemon.get_info()
|
||||
assert res.height == height
|
||||
assert res.top_block_hash == new_top_hash
|
||||
|
||||
|
||||
class Guard:
|
||||
def __enter__(self):
|
||||
|
|
|
@ -139,6 +139,25 @@ class P2PTest():
|
|||
assert res.height == height + 6
|
||||
assert res.top_block_hash == daemon2_top_block_hash
|
||||
|
||||
# disconnect and mine a lot on daemon3
|
||||
daemon2.out_peers(0)
|
||||
daemon3.out_peers(0)
|
||||
res = daemon3.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 500)
|
||||
|
||||
# reconnect and wait for sync
|
||||
daemon2.out_peers(8)
|
||||
daemon3.out_peers(8)
|
||||
loops = 100
|
||||
while True:
|
||||
res2 = daemon2.get_info()
|
||||
res3 = daemon3.get_info()
|
||||
if res2.top_block_hash == res3.top_block_hash:
|
||||
break
|
||||
time.sleep(10)
|
||||
loops -= 1
|
||||
assert loops >= 0
|
||||
|
||||
|
||||
def test_p2p_tx_propagation(self):
|
||||
print('Testing P2P tx propagation')
|
||||
daemon2 = Daemon(idx = 2)
|
||||
|
|
Loading…
Reference in New Issue