diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 80d8bb62d..5dfa7859a 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -272,6 +272,7 @@ namespace cryptonote void (*long_poll_trigger)(tx_memory_pool& pool) = [](tx_memory_pool&) { need_core_init(); }; quorumnet_new_proc *quorumnet_new = [](core&) -> void* { need_core_init(); }; + quorumnet_init_proc *quorumnet_init = [](core&, void*) { need_core_init(); }; quorumnet_delete_proc *quorumnet_delete = [](void*&) { need_core_init(); }; quorumnet_relay_obligation_votes_proc *quorumnet_relay_obligation_votes = [](void*, const std::vector&) { need_core_init(); }; quorumnet_send_blink_proc *quorumnet_send_blink = [](core&, const std::string&) -> std::future> { need_core_init(); }; @@ -1073,6 +1074,7 @@ namespace cryptonote m_quorumnet_state = quorumnet_new(*this); } + quorumnet_init(*this, m_quorumnet_state); } void core::start_lokimq() { diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 509fd0831..b21dbe36d 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -83,6 +83,10 @@ namespace cryptonote // passed into all the other callbacks below so that the callbacks can recast it into whatever it // should be. using quorumnet_new_proc = void *(core &core); + // Initializes quorumnet; unlike `quorumnet_new_proc` this needs to be called for all nodes, not + // just service nodes. The second argument should be the `quorumnet_new` return value if a + // service node, nullptr if not. + using quorumnet_init_proc = void (core &core, void *self); // Destroys the quorumnet state; called on shutdown *after* the LokiMQ object has been destroyed. // Should destroy the state object and set the pointer reference to nullptr. using quorumnet_delete_proc = void (void *&self); @@ -100,6 +104,7 @@ namespace cryptonote extern void (*long_poll_trigger)(tx_memory_pool& pool); extern quorumnet_new_proc *quorumnet_new; + extern quorumnet_init_proc *quorumnet_init; extern quorumnet_delete_proc *quorumnet_delete; extern quorumnet_relay_obligation_votes_proc *quorumnet_relay_obligation_votes; extern quorumnet_send_blink_proc *quorumnet_send_blink; diff --git a/src/cryptonote_protocol/quorumnet.cpp b/src/cryptonote_protocol/quorumnet.cpp index dc4335fee..b90490880 100644 --- a/src/cryptonote_protocol/quorumnet.cpp +++ b/src/cryptonote_protocol/quorumnet.cpp @@ -113,12 +113,10 @@ crypto::x25519_public_key x25519_from_string(std::string_view pubkey) { return x25519_pub; } -void setup_endpoints(QnetState& qnet); +void setup_endpoints(cryptonote::core& core, void* obj); void *new_qnetstate(cryptonote::core& core) { - QnetState* obj = new QnetState(core); - setup_endpoints(*obj); - return obj; + return new QnetState(core); } void delete_qnetstate(void *&obj) { @@ -1520,7 +1518,7 @@ void pulse_relay_message_to_quorum(void *self, pulse::message const &msg, servic } - QnetState &qnet = *static_cast(self); + auto &qnet = QnetState::from(self); if (block_producer) { service_nodes::quorum const *quorum_ptr = &quorum; @@ -1673,6 +1671,7 @@ void handle_pulse_signed_block(Message &m, QnetState &qnet) /// cryptonote_protocol). Called from daemon/daemon.cpp. Also registers quorum command callbacks. void init_core_callbacks() { cryptonote::quorumnet_new = new_qnetstate; + cryptonote::quorumnet_init = setup_endpoints; cryptonote::quorumnet_delete = delete_qnetstate; cryptonote::quorumnet_relay_obligation_votes = relay_obligation_votes; cryptonote::quorumnet_send_blink = send_blink; @@ -1680,24 +1679,38 @@ void init_core_callbacks() { } namespace { -void setup_endpoints(QnetState& qnet) { - auto& lmq = qnet.lmq; +void setup_endpoints(cryptonote::core& core, void* obj) { + auto& lmq = core.get_lmq(); - // quorum.*: commands between quorum members, requires that both side of the connection is a SN - lmq.add_category("quorum", Access{AuthLevel::none, true /*remote sn*/, true /*local sn*/}, 2 /*reserved threads*/) - // Receives an obligation vote - .add_command("vote_ob", [&qnet](Message& m) { handle_obligation_vote(m, qnet); }) - // Receives blink tx signatures or rejections between quorum members (either original or - // forwarded). These are propagated by the receiver if new - .add_command("blink_sign", [&qnet](Message& m) { handle_blink_signature(m, qnet); }) - ; + if (core.service_node()) { + if (!obj) + throw std::logic_error{"qnet initialization failure: quorumnet_new must be called for service node operation"}; + auto& qnet = QnetState::from(obj); + // quorum.*: commands between quorum members, requires that both side of the connection is a SN + lmq.add_category("quorum", Access{AuthLevel::none, true /*remote sn*/, true /*local sn*/}, 2 /*reserved threads*/) + // Receives an obligation vote + .add_command("vote_ob", [&qnet](Message& m) { handle_obligation_vote(m, qnet); }) + // Receives blink tx signatures or rejections between quorum members (either original or + // forwarded). These are propagated by the receiver if new + .add_command("blink_sign", [&qnet](Message& m) { handle_blink_signature(m, qnet); }) + ; - // blink.*: commands sent to blink quorum members from anyone (e.g. blink submission) - lmq.add_category("blink", Access{AuthLevel::none, false /*remote sn*/, true /*local sn*/}, 1 /*reserved thread*/) - // Receives a new blink tx submission from an external node, or forward from other quorum - // members who received it from an external node. - .add_command("submit", [&qnet](Message& m) { handle_blink(m, qnet); }) - ; + // blink.*: commands sent to blink quorum members from anyone (e.g. blink submission) + lmq.add_category("blink", Access{AuthLevel::none, false /*remote sn*/, true /*local sn*/}, 1 /*reserved thread*/) + // Receives a new blink tx submission from an external node, or forward from other quorum + // members who received it from an external node. + .add_command("submit", [&qnet](Message& m) { handle_blink(m, qnet); }) + ; + + lmq.add_category(PULSE_CMD_CATEGORY, Access{AuthLevel::none, true /*remote sn*/, true /*local sn*/}, 1 /*reserved thread*/) + .add_command(PULSE_CMD_VALIDATOR_BIT, [&qnet](Message& m) { handle_pulse_participation_bit_or_bitset(m, qnet, false /*bitset*/); }) + .add_command(PULSE_CMD_VALIDATOR_BITSET, [&qnet](Message& m) { handle_pulse_participation_bit_or_bitset(m, qnet, true /*bitset*/); }) + .add_command(PULSE_CMD_BLOCK_TEMPLATE, [&qnet](Message& m) { handle_pulse_block_template(m, qnet); }) + .add_command(PULSE_CMD_RANDOM_VALUE_HASH, [&qnet](Message& m) { handle_pulse_random_value_hash(m, qnet); }) + .add_command(PULSE_CMD_RANDOM_VALUE, [&qnet](Message& m) { handle_pulse_random_value(m, qnet); }) + .add_command(PULSE_CMD_SIGNED_BLOCK, [&qnet](Message& m) { handle_pulse_signed_block(m, qnet); }) + ; + } // bl.*: responses to blinks sent from quorum members back to the node who submitted the blink lmq.add_category("bl", Access{AuthLevel::none, true /*remote sn*/, false /*local sn*/}) @@ -1716,15 +1729,6 @@ void setup_endpoints(QnetState& qnet) { .add_command("good", handle_blink_success) ; - lmq.add_category(PULSE_CMD_CATEGORY, Access{AuthLevel::none, true /*remote sn*/, true /*local sn*/}, 1 /*reserved thread*/) - .add_command(PULSE_CMD_VALIDATOR_BIT, [&qnet](Message& m) { handle_pulse_participation_bit_or_bitset(m, qnet, false /*bitset*/); }) - .add_command(PULSE_CMD_VALIDATOR_BITSET, [&qnet](Message& m) { handle_pulse_participation_bit_or_bitset(m, qnet, true /*bitset*/); }) - .add_command(PULSE_CMD_BLOCK_TEMPLATE, [&qnet](Message& m) { handle_pulse_block_template(m, qnet); }) - .add_command(PULSE_CMD_RANDOM_VALUE_HASH, [&qnet](Message& m) { handle_pulse_random_value_hash(m, qnet); }) - .add_command(PULSE_CMD_RANDOM_VALUE, [&qnet](Message& m) { handle_pulse_random_value(m, qnet); }) - .add_command(PULSE_CMD_SIGNED_BLOCK, [&qnet](Message& m) { handle_pulse_signed_block(m, qnet); }) - ; - // Compatibility aliases. No longer used since 7.1.4, but can still be received from previous // 7.1.x nodes. // Transition plan: