aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvictorsintnicolaas <vicsn@users.noreply.github.com>2018-06-14 21:11:49 +0200
committervictorsintnicolaas <vicsn@users.noreply.github.com>2018-06-29 10:06:11 +0200
commit34cb6b4b703f30be89388f4cdcc5d7b6780ee988 (patch)
tree32563cb9c0fad0a9597bd80b0e0392f708dc1da8 /src
parentdb_lmdb: enable batch transactions by default (diff)
downloadmonero-34cb6b4b703f30be89388f4cdcc5d7b6780ee988.tar.xz
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
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.cpp5
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.h2
-rw-r--r--src/blockchain_db/blockchain_db.h14
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp15
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h2
-rw-r--r--src/cryptonote_basic/hardfork.h15
-rw-r--r--src/cryptonote_core/blockchain.cpp46
-rw-r--r--src/cryptonote_core/blockchain.h11
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp32
-rw-r--r--src/cryptonote_core/cryptonote_core.h2
-rw-r--r--src/daemon/daemon.cpp3
-rw-r--r--src/daemon/main.cpp5
-rw-r--r--src/p2p/net_node.inl3
-rw-r--r--src/rpc/core_rpc_server.cpp62
-rw-r--r--src/rpc/core_rpc_server.h2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h25
-rw-r--r--src/rpc/core_rpc_server_error_codes.h1
17 files changed, 231 insertions, 14 deletions
diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp
index e1b76ec1e..f827ab7c3 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.cpp
+++ b/src/blockchain_db/berkeleydb/db_bdb.cpp
@@ -1213,6 +1213,11 @@ std::vector<std::string> BlockchainBDB::get_filenames() const
return full_paths;
}
+bool BlockchainBDB::remove_data_file(const std::string& folder)
+{
+ return true;
+}
+
std::string BlockchainBDB::get_db_name() const
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
diff --git a/src/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h
index cecbba28f..c90d030a2 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.h
+++ b/src/blockchain_db/berkeleydb/db_bdb.h
@@ -244,6 +244,8 @@ public:
virtual std::vector<std::string> get_filenames() const;
+ virtual bool remove_data_file(const std::string& folder);
+
virtual std::string get_db_name() const;
virtual bool lock();
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 19ba32340..02077ac84 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -654,6 +654,20 @@ public:
*/
virtual std::vector<std::string> get_filenames() const = 0;
+ /**
+ * @brief remove file(s) storing the database
+ *
+ * This function is for resetting the database (for core tests, functional tests, etc).
+ * The function reset() is not usable because it needs to open the database file first
+ * which can fail if the existing database file is in an incompatible format.
+ * As such, this function needs to be called before calling open().
+ *
+ * @param folder The path of the folder containing the database file(s) which must not end with slash '/'.
+ *
+ * @return true if the operation is succesfull
+ */
+ virtual bool remove_data_file(const std::string& folder) const = 0;
+
// return the name of the folder the db's file(s) should reside in
/**
* @brief gets the name of the folder the BlockchainDB's file(s) should be in
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 300fb6d2f..05af0f5aa 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -1465,6 +1465,21 @@ std::vector<std::string> BlockchainLMDB::get_filenames() const
return filenames;
}
+bool BlockchainLMDB::remove_data_file(const std::string& folder) const
+{
+ const std::string filename = folder + "/data.mdb";
+ try
+ {
+ boost::filesystem::remove(filename);
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Failed to remove " << filename << ": " << e.what());
+ return false;
+ }
+ return true;
+}
+
std::string BlockchainLMDB::get_db_name() const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 4580573eb..54aa864a6 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -181,6 +181,8 @@ public:
virtual std::vector<std::string> get_filenames() const;
+ virtual bool remove_data_file(const std::string& folder) const;
+
virtual std::string get_db_name() const;
virtual bool lock();
diff --git a/src/cryptonote_basic/hardfork.h b/src/cryptonote_basic/hardfork.h
index ee5ec0596..a63a66976 100644
--- a/src/cryptonote_basic/hardfork.h
+++ b/src/cryptonote_basic/hardfork.h
@@ -220,6 +220,14 @@ namespace cryptonote
*/
uint64_t get_window_size() const { return window_size; }
+ struct Params {
+ uint8_t version;
+ uint8_t threshold;
+ uint64_t height;
+ time_t time;
+ Params(uint8_t version, uint64_t height, uint8_t threshold, time_t time): version(version), threshold(threshold), height(height), time(time) {}
+ };
+
private:
uint8_t get_block_version(uint64_t height) const;
@@ -244,13 +252,6 @@ namespace cryptonote
uint8_t original_version;
uint64_t original_version_till_height;
- struct Params {
- uint8_t version;
- uint8_t threshold;
- uint64_t height;
- time_t time;
- Params(uint8_t version, uint64_t height, uint8_t threshold, time_t time): version(version), threshold(threshold), height(height), time(time) {}
- };
std::vector<Params> heights;
std::deque<uint8_t> versions; /* rolling window of the last N blocks' versions */
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 54d8fac31..191130953 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -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);
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 769e608ca..a3cdecbb8 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -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
@@ -755,6 +756,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
*
* @return the version
@@ -1033,6 +1041,7 @@ namespace cryptonote
network_type m_nettype;
bool m_offline;
+ difficulty_type m_fixed_difficulty;
std::atomic<bool> m_cancel;
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index d2796deeb..54c88acbd 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -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");
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 17b5680e5..2d8ae7930 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -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;
/************************************************************************/
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index 48671f190..ea24e32eb 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -77,9 +77,10 @@ public:
const auto testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
const auto stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
+ const auto regtest = command_line::get_arg(vm, cryptonote::arg_regtest_on);
const auto restricted = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_restricted_rpc);
const auto main_rpc_port = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_rpc_bind_port);
- rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, main_rpc_port, "core"});
+ rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : regtest ? cryptonote::FAKECHAIN : cryptonote::MAINNET, main_rpc_port, "core"});
auto restricted_rpc_port_arg = cryptonote::core_rpc_server::arg_rpc_restricted_bind_port;
if(!command_line::is_arg_defaulted(vm, restricted_rpc_port_arg))
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 49494e889..711de0736 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -162,9 +162,10 @@ int main(int argc, char const * argv[])
const bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- if (testnet && stagenet)
+ const bool regtest = command_line::get_arg(vm, cryptonote::arg_regtest_on);
+ if (testnet + stagenet + regtest > 1)
{
- std::cerr << "Can't specify more than one of --tesnet and --stagenet" << ENDL;
+ std::cerr << "Can't specify more than one of --tesnet and --stagenet and --regtest" << ENDL;
return 1;
}
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 9b21705ec..de0aa169b 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -382,6 +382,9 @@ namespace nodetool
full_addrs.insert("162.210.173.150:38080");
full_addrs.insert("162.210.173.151:38080");
}
+ else if (nettype == cryptonote::FAKECHAIN)
+ {
+ }
else
{
full_addrs.insert("107.152.130.98:18080");
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index aa105567c..c0b1d8891 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1209,6 +1209,68 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_generateblocks(const COMMAND_RPC_GENERATEBLOCKS::request& req, COMMAND_RPC_GENERATEBLOCKS::response& res, epee::json_rpc::error& error_resp)
+ {
+ PERF_TIMER(on_generateblocks);
+
+ CHECK_CORE_READY();
+
+ res.status = CORE_RPC_STATUS_OK;
+
+ if(m_core.get_nettype() != FAKECHAIN)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_REGTEST_REQUIRED;
+ error_resp.message = "Regtest required when generating blocks";
+ return false;
+ }
+
+ COMMAND_RPC_GETBLOCKTEMPLATE::request template_req;
+ COMMAND_RPC_GETBLOCKTEMPLATE::response template_res;
+ COMMAND_RPC_SUBMITBLOCK::request submit_req;
+ COMMAND_RPC_SUBMITBLOCK::response submit_res;
+
+ template_req.reserve_size = 1;
+ template_req.wallet_address = req.wallet_address;
+ submit_req.push_back(boost::value_initialized<std::string>());
+ res.height = m_core.get_blockchain_storage().get_current_blockchain_height();
+
+ bool r;
+
+ for(size_t i = 0; i < req.amount_of_blocks; i++)
+ {
+ r = on_getblocktemplate(template_req, template_res, error_resp);
+ res.status = template_res.status;
+
+ if (!r) return false;
+
+ blobdata blockblob;
+ if(!string_tools::parse_hexstr_to_binbuff(template_res.blocktemplate_blob, blockblob))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
+ error_resp.message = "Wrong block blob";
+ return false;
+ }
+ block b = AUTO_VAL_INIT(b);
+ if(!parse_and_validate_block_from_blob(blockblob, b))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
+ error_resp.message = "Wrong block blob";
+ return false;
+ }
+ miner::find_nonce_for_given_block(b, template_res.difficulty, template_res.height);
+
+ submit_req.front() = string_tools::buff_to_hex_nodelimer(block_to_blob(b));
+ r = on_submitblock(submit_req, submit_res, error_resp);
+ res.status = submit_res.status;
+
+ if (!r) return false;
+
+ res.height = template_res.height;
+ }
+
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
uint64_t core_rpc_server::get_block_reward(const block& blk)
{
uint64_t reward = 0;
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 324f219f8..5e62bc4a8 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -129,6 +129,7 @@ namespace cryptonote
MAP_JON_RPC_WE("getblocktemplate", on_getblocktemplate, COMMAND_RPC_GETBLOCKTEMPLATE)
MAP_JON_RPC_WE("submit_block", on_submitblock, COMMAND_RPC_SUBMITBLOCK)
MAP_JON_RPC_WE("submitblock", on_submitblock, COMMAND_RPC_SUBMITBLOCK)
+ MAP_JON_RPC_WE_IF("generateblocks", on_generateblocks, COMMAND_RPC_GENERATEBLOCKS, !m_restricted)
MAP_JON_RPC_WE("get_last_block_header", on_get_last_block_header, COMMAND_RPC_GET_LAST_BLOCK_HEADER)
MAP_JON_RPC_WE("getlastblockheader", on_get_last_block_header, COMMAND_RPC_GET_LAST_BLOCK_HEADER)
MAP_JON_RPC_WE("get_block_header_by_hash", on_get_block_header_by_hash, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH)
@@ -196,6 +197,7 @@ namespace cryptonote
bool on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp);
bool on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res, epee::json_rpc::error& error_resp);
bool on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res, epee::json_rpc::error& error_resp);
+ bool on_generateblocks(const COMMAND_RPC_GENERATEBLOCKS::request& req, COMMAND_RPC_GENERATEBLOCKS::response& res, epee::json_rpc::error& error_resp);
bool on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp);
bool on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp);
bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp);
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 70e186848..c0b0577c7 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -1149,6 +1149,31 @@ namespace cryptonote
END_KV_SERIALIZE_MAP()
};
};
+
+ struct COMMAND_RPC_GENERATEBLOCKS
+ {
+ struct request
+ {
+ uint64_t amount_of_blocks;
+ std::string wallet_address;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(amount_of_blocks)
+ KV_SERIALIZE(wallet_address)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ uint64_t height;
+ std::string status;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(height)
+ KV_SERIALIZE(status)
+ END_KV_SERIALIZE_MAP()
+ };
+ };
struct block_header_response
{
diff --git a/src/rpc/core_rpc_server_error_codes.h b/src/rpc/core_rpc_server_error_codes.h
index 69caaa6a6..5a754749f 100644
--- a/src/rpc/core_rpc_server_error_codes.h
+++ b/src/rpc/core_rpc_server_error_codes.h
@@ -42,5 +42,6 @@
#define CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB_SIZE -10
#define CORE_RPC_ERROR_CODE_UNSUPPORTED_RPC -11
#define CORE_RPC_ERROR_CODE_MINING_TO_SUBADDRESS -12
+#define CORE_RPC_ERROR_CODE_REGTEST_REQUIRED -13