Refactor multiple SON support processing

This commit is contained in:
Srdjan Obucina 2020-03-20 23:04:08 +01:00
parent 90e58cd01f
commit 84c9ea1a53
4 changed files with 133 additions and 101 deletions

View file

@ -27,8 +27,9 @@ public:
std::unique_ptr<detail::peerplays_sidechain_plugin_impl> my;
std::set<chain::son_id_type> &get_sons();
son_id_type &get_current_son_id();
son_object get_son_object(son_id_type son_id);
const son_id_type get_current_son_id();
const son_object get_current_son_object();
const son_object get_son_object(son_id_type son_id);
bool is_active_son(son_id_type son_id);
fc::ecc::private_key get_private_key(son_id_type son_id);
fc::ecc::private_key get_private_key(chain::public_key_type public_key);

View file

@ -33,8 +33,9 @@ public:
void plugin_startup();
std::set<chain::son_id_type> &get_sons();
son_id_type &get_current_son_id();
son_object get_son_object(son_id_type son_id);
const son_id_type get_current_son_id();
const son_object get_current_son_object();
const son_object get_son_object(son_id_type son_id);
bool is_active_son(son_id_type son_id);
fc::ecc::private_key get_private_key(son_id_type son_id);
fc::ecc::private_key get_private_key(chain::public_key_type public_key);
@ -226,11 +227,15 @@ std::set<chain::son_id_type> &peerplays_sidechain_plugin_impl::get_sons() {
return sons;
}
son_id_type &peerplays_sidechain_plugin_impl::get_current_son_id() {
const son_id_type peerplays_sidechain_plugin_impl::get_current_son_id() {
return current_son_id;
}
son_object peerplays_sidechain_plugin_impl::get_son_object(son_id_type son_id) {
const son_object peerplays_sidechain_plugin_impl::get_current_son_object() {
return get_son_object(current_son_id);
}
const son_object peerplays_sidechain_plugin_impl::get_son_object(son_id_type son_id) {
const auto &idx = plugin.database().get_index_type<chain::son_index>().indices().get<by_id>();
auto son_obj = idx.find(son_id);
if (son_obj == idx.end())
@ -289,7 +294,7 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() {
for (son_id_type son_id : sons) {
if (is_active_son(son_id) || get_son_object(son_id).status == chain::son_status::in_maintenance) {
ilog("peerplays_sidechain_plugin: sending heartbeat for SON ${son}", ("son", son_id));
ilog("Sending heartbeat for SON ${son}", ("son", son_id));
chain::son_heartbeat_operation op;
op.owner_account = get_son_object(son_id).son_account;
op.son_id = son_id;
@ -302,7 +307,7 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() {
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
return true;
} catch (fc::exception e) {
ilog("peerplays_sidechain_plugin_impl: sending heartbeat failed with exception ${e}", ("e", e.what()));
elog("Sending heartbeat failed with exception ${e}", ("e", e.what()));
return false;
}
});
@ -328,38 +333,63 @@ void peerplays_sidechain_plugin_impl::son_processing() {
return;
}
chain::son_id_type next_son_id = plugin.database().get_scheduled_son(1);
ilog("peerplays_sidechain_plugin_impl: Scheduled SON ${son}", ("son", next_son_id));
// Tasks that are executed by all active SONs, no matter if scheduled
// E.g. sending approvals and signing
approve_proposals();
// Tasks that are executed by scheduled and active SON
if (sons.find(next_son_id) != sons.end()) {
current_son_id = next_son_id;
create_son_down_proposals();
create_son_deregister_proposals();
recreate_primary_wallet();
process_deposits();
process_withdrawals();
process_sidechain_transactions();
send_sidechain_transactions();
fc::time_point now_fine = fc::time_point::now();
fc::time_point_sec now = now_fine + fc::microseconds(500000);
if (plugin.database().get_slot_time(1) < now) {
return; // Not synced
}
}
uint32_t slot = 1; //plugin.database().get_slot_at_time(now);
if (slot == 0) {
return; // Not time yet
}
//assert(now > plugin.database().head_block_time());
chain::son_id_type scheduled_son_id = plugin.database().get_scheduled_son(slot);
fc::time_point_sec scheduled_time = plugin.database().get_slot_time(slot);
ilog("Slot: ${slot} Scheduled SON: ${scheduled_son_id} Scheduled time: ${scheduled_time} Now: ${now} ",
("slot", slot)("scheduled_son_id", scheduled_son_id)("scheduled_time", scheduled_time)("now", now));
for (son_id_type son_id : plugin.get_sons()) {
if (plugin.is_active_son(son_id)) {
current_son_id = son_id;
// Tasks that are executed by all active SONs, no matter if scheduled
// E.g. sending approvals and signing
approve_proposals();
process_sidechain_transactions();
// Tasks that are executed by scheduled and active SON
if (current_son_id == scheduled_son_id) {
create_son_down_proposals();
create_son_deregister_proposals();
recreate_primary_wallet();
process_deposits();
process_withdrawals();
send_sidechain_transactions();
}
} else {
// Tasks that are executed by previously active SONs
// E.g. sending approvals and signing that SON was required to do while it was active
//approve_leftover_proposals(); ???
//process_leftover_sidechain_transactions(); ???
}
}
} // namespace detail
void peerplays_sidechain_plugin_impl::approve_proposals() {
auto approve_proposal = [&](const chain::son_id_type &son_id, const chain::proposal_id_type &proposal_id) {
ilog("peerplays_sidechain_plugin: sending approval for ${p} from ${s}", ("p", proposal_id)("s", son_id));
ilog("Sending approval for ${p} from ${s}", ("p", proposal_id)("s", son_id));
chain::proposal_update_operation puo;
puo.fee_paying_account = get_son_object(son_id).son_account;
puo.proposal = proposal_id;
@ -372,7 +402,7 @@ void peerplays_sidechain_plugin_impl::approve_proposals() {
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
return true;
} catch (fc::exception e) {
ilog("peerplays_sidechain_plugin_impl: sending approval failed with exception ${e}", ("e", e.what()));
elog("Sending approval failed with exception ${e}", ("e", e.what()));
return false;
}
});
@ -386,59 +416,54 @@ void peerplays_sidechain_plugin_impl::approve_proposals() {
}
for (const auto proposal_id : proposals) {
for (son_id_type son_id : sons) {
if (!is_active_son(son_id)) {
continue;
}
const object *obj = plugin.database().find_object(proposal_id);
const chain::proposal_object *proposal_ptr = dynamic_cast<const chain::proposal_object *>(obj);
if (proposal_ptr == nullptr) {
continue;
}
const proposal_object proposal = *proposal_ptr;
if (proposal.available_active_approvals.find(get_son_object(son_id).son_account) != proposal.available_active_approvals.end()) {
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_report_down_operation>::value) {
approve_proposal(son_id, proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_delete_operation>::value) {
approve_proposal(son_id, proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_update_operation>::value) {
approve_proposal(son_id, proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_deposit_create_operation>::value) {
approve_proposal(son_id, proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_deposit_process_operation>::value) {
approve_proposal(son_id, proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_withdraw_create_operation>::value) {
approve_proposal(son_id, proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value) {
approve_proposal(son_id, proposal.id);
continue;
}
approve_proposal(son_id, proposal.id);
const object *obj = plugin.database().find_object(proposal_id);
const chain::proposal_object *proposal_ptr = dynamic_cast<const chain::proposal_object *>(obj);
if (proposal_ptr == nullptr) {
continue;
}
const proposal_object proposal = *proposal_ptr;
if (proposal.available_active_approvals.find(get_current_son_object().son_account) != proposal.available_active_approvals.end()) {
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_report_down_operation>::value) {
approve_proposal(get_current_son_id(), proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_delete_operation>::value) {
approve_proposal(get_current_son_id(), proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_update_operation>::value) {
approve_proposal(get_current_son_id(), proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_deposit_create_operation>::value) {
approve_proposal(get_current_son_id(), proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_deposit_process_operation>::value) {
approve_proposal(get_current_son_id(), proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_withdraw_create_operation>::value) {
approve_proposal(get_current_son_id(), proposal.id);
continue;
}
if (proposal.proposed_transaction.operations.size() == 1 && proposal.proposed_transaction.operations[0].which() == chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value) {
approve_proposal(get_current_son_id(), proposal.id);
continue;
}
approve_proposal(get_current_son_id(), proposal.id);
}
}
@ -477,7 +502,7 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() {
int64_t down_threshold = gpo.parameters.son_down_time();
if (((son_obj->status == chain::son_status::active) || (son_obj->status == chain::son_status::request_maintenance)) &&
((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) {
ilog("peerplays_sidechain_plugin: sending son down proposal for ${t} from ${s}", ("t", std::string(object_id_type(son_obj->id)))("s", std::string(object_id_type(my_son_id))));
ilog("Sending son down proposal for ${t} from ${s}", ("t", std::string(object_id_type(son_obj->id)))("s", std::string(object_id_type(my_son_id))));
chain::proposal_create_operation op = create_son_down_proposal(son_inf.son_id, last_active_ts);
chain::signed_transaction trx = d.create_signed_transaction(plugin.get_private_key(get_son_object(my_son_id).signing_key), op);
fc::future<bool> fut = fc::async([&]() {
@ -487,7 +512,7 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() {
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
return true;
} catch (fc::exception e) {
ilog("peerplays_sidechain_plugin_impl: sending son down proposal failed with exception ${e}", ("e", e.what()));
elog("Sending son down proposal failed with exception ${e}", ("e", e.what()));
return false;
}
});
@ -512,7 +537,7 @@ void peerplays_sidechain_plugin_impl::create_son_deregister_proposals() {
auto op = d.create_son_deregister_proposal(son, get_son_object(my_son_id).son_account);
if (op.valid()) {
// Signing and pushing into the txs to be included in the block
ilog("peerplays_sidechain_plugin: sending son deregister proposal for ${p} from ${s}", ("p", son)("s", my_son_id));
ilog("Sending son deregister proposal for ${p} from ${s}", ("p", son)("s", my_son_id));
chain::signed_transaction trx = d.create_signed_transaction(plugin.get_private_key(get_son_object(my_son_id).signing_key), *op);
fc::future<bool> fut = fc::async([&]() {
try {
@ -521,7 +546,7 @@ void peerplays_sidechain_plugin_impl::create_son_deregister_proposals() {
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
return true;
} catch (fc::exception e) {
ilog("peerplays_sidechain_plugin_impl: sending son dereg proposal failed with exception ${e}", ("e", e.what()));
elog("Sending son deregister proposal failed with exception ${e}", ("e", e.what()));
return false;
}
});
@ -560,7 +585,7 @@ void peerplays_sidechain_plugin_impl::on_applied_block(const signed_block &b) {
}
}
} // end namespace detail
} // namespace detail
peerplays_sidechain_plugin::peerplays_sidechain_plugin() :
my(new detail::peerplays_sidechain_plugin_impl(*this)) {
@ -581,24 +606,30 @@ void peerplays_sidechain_plugin::plugin_set_program_options(
}
void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options::variables_map &options) {
ilog("peerplays sidechain plugin: plugin_initialize()");
ilog("peerplays sidechain plugin: plugin_initialize() begin");
my->plugin_initialize(options);
ilog("peerplays sidechain plugin: plugin_initialize() end");
}
void peerplays_sidechain_plugin::plugin_startup() {
ilog("peerplays sidechain plugin: plugin_startup()");
ilog("peerplays sidechain plugin: plugin_startup() begin");
my->plugin_startup();
ilog("peerplays sidechain plugin: plugin_startup() end");
}
std::set<chain::son_id_type> &peerplays_sidechain_plugin::get_sons() {
return my->get_sons();
}
son_id_type &peerplays_sidechain_plugin::get_current_son_id() {
const son_id_type peerplays_sidechain_plugin::get_current_son_id() {
return my->get_current_son_id();
}
son_object peerplays_sidechain_plugin::get_son_object(son_id_type son_id) {
const son_object peerplays_sidechain_plugin::get_current_son_object() {
return my->get_current_son_object();
}
const son_object peerplays_sidechain_plugin::get_son_object(son_id_type son_id) {
return my->get_son_object(son_id);
}

View file

@ -269,8 +269,6 @@ void sidechain_net_handler::process_sidechain_transactions() {
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, false));
std::for_each(idx_range.first, idx_range.second, [&](const sidechain_transaction_object &sto) {
ilog("Sidechain transaction to process: ${sto}", ("sto", sto));
son_id_type invalid_signer = son_id_type(0xFFFFFFFF);
son_id_type next_signer = invalid_signer;
for (auto &signer : sto.signers) {
@ -281,6 +279,8 @@ void sidechain_net_handler::process_sidechain_transactions() {
}
if ((next_signer != invalid_signer) && (next_signer == plugin.get_current_son_id())) {
ilog("Sidechain transaction to process: ${sto}", ("sto", sto));
bool complete = false;
std::string processed_sidechain_tx = process_sidechain_transaction(sto, complete);

View file

@ -660,10 +660,10 @@ fc::http::reply bitcoin_rpc_client::send_post_request(std::string body, bool sho
show_log = true; // Log all requests temporary
if (show_log) {
ilog(" ### Request URL: ${url} ###", ("url", url));
ilog(" ### Request: ${body} ###", ("body", body));
ilog("### Request URL: ${url}", ("url", url));
ilog("### Request: ${body}", ("body", body));
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
ilog(" ### Response: ${ss} ###", ("ss", ss.str()));
ilog("### Response: ${ss}", ("ss", ss.str()));
}
return reply;