mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
Merge pull request #197 from Doy-lee/BlockchainPopBlocksCommand
Blockchain pop_blocks command
This commit is contained in:
commit
0796630ffa
|
@ -1114,6 +1114,18 @@ namespace cryptonote
|
|||
return result;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
void core::pop_blocks(size_t num_blocks_to_pop)
|
||||
{
|
||||
m_blockchain_storage.get_db().batch_start();
|
||||
for (size_t i = 0; i < num_blocks_to_pop; i++)
|
||||
{
|
||||
block blk;
|
||||
std::vector<transaction> txs;
|
||||
m_blockchain_storage.get_db().pop_block(blk, txs);
|
||||
}
|
||||
m_blockchain_storage.get_db().batch_stop();
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::handle_uptime_proof(uint64_t timestamp, const crypto::public_key& pubkey, const crypto::signature& sig)
|
||||
{
|
||||
return m_quorum_cop.handle_uptime_proof(timestamp, pubkey, sig);
|
||||
|
|
|
@ -843,6 +843,14 @@ namespace cryptonote
|
|||
*/
|
||||
uint64_t get_uptime_proof(const crypto::public_key &key) const;
|
||||
|
||||
/**
|
||||
* @brief Pop 'n' block(s) from the chain
|
||||
*
|
||||
* @param num_blocks_to_pop The number of blocks to pop
|
||||
*
|
||||
*/
|
||||
void pop_blocks(uint64_t num_blocks_to_pop);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
|
|
@ -729,4 +729,25 @@ bool t_command_parser_executor::version(const std::vector<std::string>& args)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 1)
|
||||
return false;
|
||||
|
||||
size_t num_blocks_to_pop;
|
||||
if(!epee::string_tools::get_xtype_from_string(num_blocks_to_pop, args[0]))
|
||||
{
|
||||
std::cout << "wrong starter block index parameter" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = m_executor.pop_blocks(num_blocks_to_pop);
|
||||
if (result)
|
||||
{
|
||||
raise(SIGTERM);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace daemonize
|
||||
|
|
|
@ -152,6 +152,8 @@ public:
|
|||
bool sync_info(const std::vector<std::string>& args);
|
||||
|
||||
bool version(const std::vector<std::string>& args);
|
||||
|
||||
bool pop_blocks(const std::vector<std::string>& args);
|
||||
};
|
||||
|
||||
} // namespace daemonize
|
||||
|
|
|
@ -322,6 +322,12 @@ t_command_server::t_command_server(
|
|||
, std::bind(&t_command_parser_executor::version, &m_parser, p::_1)
|
||||
, "Print version information."
|
||||
);
|
||||
m_command_lookup.set_handler(
|
||||
"pop_blocks"
|
||||
, std::bind(&t_command_parser_executor::pop_blocks, &m_parser, p::_1)
|
||||
, "pop_blocks <num_blocks_to_pop>"
|
||||
, "Remove a number of blocks from the top of the chain"
|
||||
);
|
||||
}
|
||||
|
||||
bool t_command_server::process_command_str(const std::string& cmd)
|
||||
|
|
|
@ -2666,4 +2666,64 @@ bool t_rpc_command_executor::prepare_registration()
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool t_rpc_command_executor::pop_blocks(size_t num_blocks_to_pop)
|
||||
{
|
||||
if (m_is_rpc)
|
||||
{
|
||||
std::cout << "Cannot pop_blocks over RPC as this will shut down your daemon." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_READLINE
|
||||
rdln::suspend_readline pause_readline;
|
||||
#endif
|
||||
// TODO(loki): Ideally without having to shutdown the daemon would be nice. But there's state
|
||||
// left over in terms of if you do this while syncing it will keep requesting the wrong height,
|
||||
// and the detached hooks we need to deal with.
|
||||
std::string confirmation;
|
||||
confirmation.reserve(8);
|
||||
std::cout << "This is an advanced command for modifying your blockchain.\n"
|
||||
"This command will only work in offline mode.\n"
|
||||
"Executing this command will shut down your daemon. Please restart it afterwards.\n"
|
||||
"Are you sure you wish to continue? (Y/Yes/N/No): ";
|
||||
std::cin >> confirmation;
|
||||
|
||||
if(!command_line::is_yes(confirmation))
|
||||
{
|
||||
std::cout << "Aborted." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get Height
|
||||
cryptonote::COMMAND_RPC_GET_HEIGHT::request height_req;
|
||||
cryptonote::COMMAND_RPC_GET_HEIGHT::response height_res;
|
||||
std::string fail_message = "Unsuccessful";
|
||||
|
||||
if (!m_rpc_server->on_get_height(height_req, height_res) || height_res.status != CORE_RPC_STATUS_OK)
|
||||
{
|
||||
tools::fail_msg_writer() << make_error(fail_message, height_res.status);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (num_blocks_to_pop >= height_res.height)
|
||||
{
|
||||
tools::fail_msg_writer() << "Requested to pop too many blocks. Requested: " << num_blocks_to_pop << ", current height: " << height_res.height;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pop Block
|
||||
cryptonote::COMMAND_RPC_POP_BLOCKS::request req = {};
|
||||
cryptonote::COMMAND_RPC_POP_BLOCKS::response res = {};
|
||||
req.num_blocks_to_pop = num_blocks_to_pop;
|
||||
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() << "Popped: " << num_blocks_to_pop << " blocks";
|
||||
return true;
|
||||
}
|
||||
|
||||
}// namespace daemonize
|
||||
|
|
|
@ -167,6 +167,8 @@ public:
|
|||
bool prepare_registration();
|
||||
|
||||
bool print_sn(const std::vector<std::string> &args);
|
||||
|
||||
bool pop_blocks(size_t num_blocks_to_pop);
|
||||
};
|
||||
|
||||
} // namespace daemonize
|
||||
|
|
|
@ -2004,6 +2004,30 @@ namespace cryptonote
|
|||
return r;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
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);
|
||||
|
||||
// TODO(loki): It'd be nice not to need to be offline, but it makes
|
||||
// implementation much easier to not handle any race conditions right now.
|
||||
// And this is a really handy feature for debugging chains.
|
||||
|
||||
// TODO(loki): This doesn't activate service node lists rollbacks. But will
|
||||
// trigger a rescan from scratch. Again simpler to not handle right now.
|
||||
// Putting the Blockchaindetached hook in the pop blocks call may work, but
|
||||
// haven't investigated the repercussions of that.
|
||||
if (!m_core.offline())
|
||||
{
|
||||
res.status = "Daemon must be running in offline mode to pop blocks.";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_core.pop_blocks(req.num_blocks_to_pop);
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_service_node_key(const COMMAND_RPC_GET_SERVICE_NODE_KEY::request& req, COMMAND_RPC_GET_SERVICE_NODE_KEY::response& res, epee::json_rpc::error &error_resp)
|
||||
{
|
||||
PERF_TIMER(on_get_service_node_key);
|
||||
|
|
|
@ -197,6 +197,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_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res);
|
||||
bool on_get_quorum_state(const COMMAND_RPC_GET_QUORUM_STATE::request& req, COMMAND_RPC_GET_QUORUM_STATE::response& res);
|
||||
bool on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request& req, COMMAND_RPC_POP_BLOCKS::response& res);
|
||||
|
||||
//json_rpc
|
||||
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res);
|
||||
|
|
|
@ -2435,4 +2435,23 @@ namespace cryptonote
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_POP_BLOCKS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
size_t num_blocks_to_pop;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(num_blocks_to_pop)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue