add --regtest and --fixed-difficulty for regression testing

on_generateblocks RPC call combines functionality from the on_getblocktemplate and on_submitblock RPC calls to allow rapid block creation. Difficulty is set permanently to 1 for regtest.
Makes use of FAKECHAIN network type, but takes hard fork heights from mainchain
Default reserve_size in generate_blocks RPC call is now 1. If it is 0, the following error occurs 'Failed to calculate offset for'.
Queries hard fork heights info of other network types
This commit is contained in:
victorsintnicolaas 2018-06-14 21:11:49 +02:00
parent 149da420e9
commit 34cb6b4b70
18 changed files with 232 additions and 14 deletions

View file

@ -329,7 +329,7 @@ uint64_t Blockchain::get_current_blockchain_height() const
//------------------------------------------------------------------
//FIXME: possibly move this into the constructor, to avoid accidentally
// dereferencing a null BlockchainDB pointer
bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options)
bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty)
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_tx_pool);
@ -351,6 +351,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
m_nettype = test_options != NULL ? FAKECHAIN : nettype;
m_offline = offline;
m_fixed_difficulty = fixed_difficulty;
if (m_hardfork == nullptr)
{
if (m_nettype == FAKECHAIN || m_nettype == STAGENET)
@ -805,6 +806,11 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph
// less blocks than desired if there aren't enough.
difficulty_type Blockchain::get_difficulty_for_next_block()
{
if (m_fixed_difficulty)
{
return m_db->height() ? m_fixed_difficulty : 1;
}
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_difficulty_lock);
@ -1007,6 +1013,11 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
// an alternate chain.
difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std::list<blocks_ext_by_hash::iterator>& alt_chain, block_extended_info& bei) const
{
if (m_fixed_difficulty)
{
return m_db->height() ? m_fixed_difficulty : 1;
}
LOG_PRINT_L3("Blockchain::" << __func__);
std::vector<uint64_t> timestamps;
std::vector<difficulty_type> cumulative_difficulties;
@ -4374,6 +4385,39 @@ HardFork::State Blockchain::get_hard_fork_state() const
return m_hardfork->get_state();
}
const std::vector<HardFork::Params>& Blockchain::get_hard_fork_heights(network_type nettype)
{
static const std::vector<HardFork::Params> mainnet_heights = []()
{
std::vector<HardFork::Params> heights;
for (const auto& i : mainnet_hard_forks)
heights.emplace_back(i.version, i.height, i.threshold, i.time);
return heights;
}();
static const std::vector<HardFork::Params> testnet_heights = []()
{
std::vector<HardFork::Params> heights;
for (const auto& i : testnet_hard_forks)
heights.emplace_back(i.version, i.height, i.threshold, i.time);
return heights;
}();
static const std::vector<HardFork::Params> stagenet_heights = []()
{
std::vector<HardFork::Params> heights;
for (const auto& i : stagenet_hard_forks)
heights.emplace_back(i.version, i.height, i.threshold, i.time);
return heights;
}();
static const std::vector<HardFork::Params> dummy;
switch (nettype)
{
case MAINNET: return mainnet_heights;
case TESTNET: return testnet_heights;
case STAGENET: return stagenet_heights;
default: return dummy;
}
}
bool Blockchain::get_hard_fork_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
{
return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);

View file

@ -114,10 +114,11 @@ namespace cryptonote
* @param nettype network type
* @param offline true if running offline, else false
* @param test_options test parameters
* @param fixed_difficulty fixed difficulty for testing purposes; 0 means disabled
*
* @return true on success, false if any initialization steps fail
*/
bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL);
bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0);
/**
* @brief Initialize the Blockchain state
@ -754,6 +755,13 @@ namespace cryptonote
*/
HardFork::State get_hard_fork_state() const;
/**
* @brief gets the hardfork heights of given network
*
* @return the HardFork object
*/
static const std::vector<HardFork::Params>& get_hard_fork_heights(network_type nettype);
/**
* @brief gets the current hardfork version in use/voted for
*
@ -1033,6 +1041,7 @@ namespace cryptonote
network_type m_nettype;
bool m_offline;
difficulty_type m_fixed_difficulty;
std::atomic<bool> m_cancel;

View file

@ -76,6 +76,16 @@ namespace cryptonote
, "Run on stagenet. The wallet must be launched with --stagenet flag."
, false
};
const command_line::arg_descriptor<bool> arg_regtest_on = {
"regtest"
, "Run in a regression testing mode."
, false
};
const command_line::arg_descriptor<difficulty_type> arg_fixed_difficulty = {
"fixed-difficulty"
, "Fixed difficulty used for testing."
, 0
};
const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir = {
"data-dir"
, "Specify data directory"
@ -252,6 +262,8 @@ namespace cryptonote
command_line::add_arg(desc, arg_testnet_on);
command_line::add_arg(desc, arg_stagenet_on);
command_line::add_arg(desc, arg_regtest_on);
command_line::add_arg(desc, arg_fixed_difficulty);
command_line::add_arg(desc, arg_dns_checkpoints);
command_line::add_arg(desc, arg_prep_blocks_threads);
command_line::add_arg(desc, arg_fast_block_sync);
@ -374,7 +386,8 @@ namespace cryptonote
{
start_time = std::time(nullptr);
if (test_options != NULL)
const bool regtest = command_line::get_arg(vm, arg_regtest_on);
if (test_options != NULL || regtest)
{
m_nettype = FAKECHAIN;
}
@ -431,6 +444,16 @@ namespace cryptonote
blockchain_db_sync_mode sync_mode = db_defaultsync;
uint64_t blocks_per_sync = 1;
if (m_nettype == FAKECHAIN)
{
// reset the db by removing the database file before opening it
if (!db->remove_data_file(filename))
{
MERROR("Failed to remove data file in " << filename);
return false;
}
}
try
{
uint64_t db_flags = 0;
@ -508,7 +531,12 @@ namespace cryptonote
m_blockchain_storage.set_user_options(blocks_threads,
blocks_per_sync, sync_mode, fast_sync);
r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, test_options);
const std::pair<uint8_t, uint64_t> regtest_hard_forks[3] = {std::make_pair(1, 0), std::make_pair(Blockchain::get_hard_fork_heights(MAINNET).back().version, 1), std::make_pair(0, 0)};
const cryptonote::test_options regtest_test_options = {
regtest_hard_forks
};
const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty);
r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty);
r = m_mempool.init(max_txpool_size);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");

View file

@ -61,6 +61,8 @@ namespace cryptonote
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_data_dir;
extern const command_line::arg_descriptor<bool, false> arg_testnet_on;
extern const command_line::arg_descriptor<bool, false> arg_stagenet_on;
extern const command_line::arg_descriptor<bool, false> arg_regtest_on;
extern const command_line::arg_descriptor<difficulty_type> arg_fixed_difficulty;
extern const command_line::arg_descriptor<bool> arg_offline;
/************************************************************************/