commit
0fccc78e39
|
@ -576,6 +576,38 @@ bool Blockchain::deinit()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
// This function removes blocks from the top of blockchain.
|
||||||
|
// It starts a batch and calls private method pop_block_from_blockchain().
|
||||||
|
void Blockchain::pop_blocks(uint64_t nblocks)
|
||||||
|
{
|
||||||
|
uint64_t i;
|
||||||
|
CRITICAL_REGION_LOCAL(m_tx_pool);
|
||||||
|
CRITICAL_REGION_LOCAL1(m_blockchain_lock);
|
||||||
|
|
||||||
|
while (!m_db->batch_start())
|
||||||
|
{
|
||||||
|
m_blockchain_lock.unlock();
|
||||||
|
m_tx_pool.unlock();
|
||||||
|
epee::misc_utils::sleep_no_w(1000);
|
||||||
|
m_tx_pool.lock();
|
||||||
|
m_blockchain_lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (i=0; i < nblocks; ++i)
|
||||||
|
{
|
||||||
|
pop_block_from_blockchain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Error when popping blocks, only " << i << " blocks are popped: " << e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_db->batch_stop();
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------
|
||||||
// This function tells BlockchainDB to remove the top block from the
|
// This function tells BlockchainDB to remove the top block from the
|
||||||
// blockchain and then returns all transactions (except the miner tx, of course)
|
// blockchain and then returns all transactions (except the miner tx, of course)
|
||||||
// from it to the tx_pool
|
// from it to the tx_pool
|
||||||
|
|
|
@ -967,6 +967,13 @@ namespace cryptonote
|
||||||
*/
|
*/
|
||||||
std::vector<time_t> get_last_block_timestamps(unsigned int blocks) const;
|
std::vector<time_t> get_last_block_timestamps(unsigned int blocks) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief removes blocks from the top of the blockchain
|
||||||
|
*
|
||||||
|
* @param nblocks number of blocks to be removed
|
||||||
|
*/
|
||||||
|
void pop_blocks(uint64_t nblocks);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// TODO: evaluate whether or not each of these typedefs are left over from blockchain_storage
|
// TODO: evaluate whether or not each of these typedefs are left over from blockchain_storage
|
||||||
|
|
|
@ -674,6 +674,31 @@ bool t_command_parser_executor::sync_info(const std::vector<std::string>& args)
|
||||||
return m_executor.sync_info();
|
return m_executor.sync_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
|
||||||
|
{
|
||||||
|
if (args.size() != 1)
|
||||||
|
{
|
||||||
|
std::cout << "Exactly one parameter is needed" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uint64_t nblocks = boost::lexical_cast<uint64_t>(args[0]);
|
||||||
|
if (nblocks < 1)
|
||||||
|
{
|
||||||
|
std::cout << "number of blocks must be greater than 0" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return m_executor.pop_blocks(nblocks);
|
||||||
|
}
|
||||||
|
catch (const boost::bad_lexical_cast&)
|
||||||
|
{
|
||||||
|
std::cout << "number of blocks must be a number greater than 0" << std::endl;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool t_command_parser_executor::version(const std::vector<std::string>& args)
|
bool t_command_parser_executor::version(const std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
|
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
|
||||||
|
|
|
@ -139,6 +139,8 @@ public:
|
||||||
|
|
||||||
bool sync_info(const std::vector<std::string>& args);
|
bool sync_info(const std::vector<std::string>& args);
|
||||||
|
|
||||||
|
bool pop_blocks(const std::vector<std::string>& args);
|
||||||
|
|
||||||
bool version(const std::vector<std::string>& args);
|
bool version(const std::vector<std::string>& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,12 @@ t_command_server::t_command_server(
|
||||||
, std::bind(&t_command_parser_executor::sync_info, &m_parser, p::_1)
|
, std::bind(&t_command_parser_executor::sync_info, &m_parser, p::_1)
|
||||||
, "Print information about the blockchain sync state."
|
, "Print information about the blockchain sync state."
|
||||||
);
|
);
|
||||||
|
m_command_lookup.set_handler(
|
||||||
|
"pop_blocks"
|
||||||
|
, std::bind(&t_command_parser_executor::pop_blocks, &m_parser, p::_1)
|
||||||
|
, "pop_blocks <nblocks>"
|
||||||
|
, "Remove blocks from end of blockchain"
|
||||||
|
);
|
||||||
m_command_lookup.set_handler(
|
m_command_lookup.set_handler(
|
||||||
"version"
|
"version"
|
||||||
, std::bind(&t_command_parser_executor::version, &m_parser, p::_1)
|
, std::bind(&t_command_parser_executor::version, &m_parser, p::_1)
|
||||||
|
|
|
@ -1967,4 +1967,31 @@ bool t_rpc_command_executor::sync_info()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool t_rpc_command_executor::pop_blocks(uint64_t num_blocks)
|
||||||
|
{
|
||||||
|
cryptonote::COMMAND_RPC_POP_BLOCKS::request req;
|
||||||
|
cryptonote::COMMAND_RPC_POP_BLOCKS::response res;
|
||||||
|
std::string fail_message = "pop_blocks failed";
|
||||||
|
|
||||||
|
req.nblocks = num_blocks;
|
||||||
|
if (m_is_rpc)
|
||||||
|
{
|
||||||
|
if (!m_rpc_client->rpc_request(req, res, "/pop_blocks", fail_message.c_str()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!m_rpc_server->on_pop_blocks(req, res) || res.status != CORE_RPC_STATUS_OK)
|
||||||
|
{
|
||||||
|
tools::fail_msg_writer() << make_error(fail_message, res.status);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tools::success_msg_writer() << "new height: " << res.height;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}// namespace daemonize
|
}// namespace daemonize
|
||||||
|
|
|
@ -152,6 +152,8 @@ public:
|
||||||
bool relay_tx(const std::string &txid);
|
bool relay_tx(const std::string &txid);
|
||||||
|
|
||||||
bool sync_info();
|
bool sync_info();
|
||||||
|
|
||||||
|
bool pop_blocks(uint64_t num_blocks);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace daemonize
|
} // namespace daemonize
|
||||||
|
|
|
@ -2032,6 +2032,18 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool core_rpc_server::on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request& req, COMMAND_RPC_POP_BLOCKS::response& res)
|
||||||
|
{
|
||||||
|
PERF_TIMER(on_pop_blocks);
|
||||||
|
|
||||||
|
m_core.get_blockchain_storage().pop_blocks(req.nblocks);
|
||||||
|
|
||||||
|
res.height = m_core.get_current_blockchain_height();
|
||||||
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp)
|
bool core_rpc_server::on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp)
|
||||||
{
|
{
|
||||||
PERF_TIMER(on_relay_tx);
|
PERF_TIMER(on_relay_tx);
|
||||||
|
|
|
@ -117,6 +117,7 @@ namespace cryptonote
|
||||||
MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS)
|
MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS)
|
||||||
MAP_URI_AUTO_JON2_IF("/update", on_update, COMMAND_RPC_UPDATE, !m_restricted)
|
MAP_URI_AUTO_JON2_IF("/update", on_update, COMMAND_RPC_UPDATE, !m_restricted)
|
||||||
MAP_URI_AUTO_BIN2("/get_output_distribution.bin", on_get_output_distribution_bin, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION)
|
MAP_URI_AUTO_BIN2("/get_output_distribution.bin", on_get_output_distribution_bin, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION)
|
||||||
|
MAP_URI_AUTO_JON2_IF("/pop_blocks", on_pop_blocks, COMMAND_RPC_POP_BLOCKS, !m_restricted)
|
||||||
BEGIN_JSON_RPC_MAP("/json_rpc")
|
BEGIN_JSON_RPC_MAP("/json_rpc")
|
||||||
MAP_JON_RPC("get_block_count", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
|
MAP_JON_RPC("get_block_count", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
|
||||||
MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
|
MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
|
||||||
|
@ -188,6 +189,7 @@ namespace cryptonote
|
||||||
bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res);
|
bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res);
|
||||||
bool on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res);
|
bool on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res);
|
||||||
bool on_get_output_distribution_bin(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res);
|
bool on_get_output_distribution_bin(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res);
|
||||||
|
bool on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request& req, COMMAND_RPC_POP_BLOCKS::response& res);
|
||||||
|
|
||||||
//json_rpc
|
//json_rpc
|
||||||
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res);
|
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res);
|
||||||
|
|
|
@ -2328,4 +2328,27 @@ namespace cryptonote
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_POP_BLOCKS
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
uint64_t nblocks;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(nblocks);
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::string status;
|
||||||
|
uint64_t height;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(status)
|
||||||
|
KV_SERIALIZE(height)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue