pulse: Formalize round times, add msg for dropped msgs

This commit is contained in:
Doyle 2020-07-31 16:23:27 +10:00
parent 2ce8f23991
commit 426290c25f
3 changed files with 45 additions and 8 deletions

View File

@ -367,8 +367,8 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
//
pulse::time_point const start_time = context.wait_next_block.round_0_start_time +
(context.wait_next_block.round * service_nodes::PULSE_TIME_PER_BLOCK);
context.wait_for_handshakes.end_time = start_time + std::chrono::seconds(10); // TODO(doyle): Formalize timings
context.wait_for_other_validator_handshake_bitsets.end_time = context.wait_for_handshakes.end_time + std::chrono::seconds(10);
context.wait_for_handshakes.end_time = start_time + service_nodes::PULSE_WAIT_FOR_HANDSHAKES_DURATION;
context.wait_for_other_validator_handshake_bitsets.end_time = context.wait_for_handshakes.end_time + service_nodes::PULSE_WAIT_FOR_OTHER_VALIDATOR_HANDSHAKES_DURATION;
//
// NOTE: Quorum
@ -536,6 +536,9 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
uint64_t expected_reward = 0;
blockchain.create_next_pulse_block_template(block, block_producer_payouts, pulse_height, expected_reward);
block.pulse.round = context.wait_next_block.round;
block.pulse.validator_participation_bits = context.submit_block_template.validator_bitset;
cryptonote::block_verification_context bvc = {};
core.handle_block_found(block, bvc);
@ -582,7 +585,10 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
// TODO(doyle): We need some lenience in time for accepting early
// handshakes in case clocks are slightly out of sync.
if (round_state != round_state::wait_for_handshakes)
{
MGINFO("Dropping " << pulse::message_type_string(msg.type) << " message from validator " << msg.quorum_position << ", expecting only handshake messages");
continue;
}
// TODO(doyle): DRY
// NOTE: Validate Signature
@ -605,7 +611,10 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
else if (msg.type == pulse::message_type::handshake_bitset)
{
if (round_state != round_state::wait_for_other_validator_handshake_bitsets)
{
MGINFO("Dropping " << pulse::message_type_string(msg.type) << " message from validator " << msg.quorum_position << ", expecting only handshake bitset messages");
continue;
}
// NOTE: Validate Signature
{

View File

@ -3,6 +3,7 @@
#include <atomic>
#include <cstdint>
#include <condition_variable>
#include <string_view>
#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "crypto/crypto.h"
@ -32,6 +33,18 @@ enum struct message_type : uint8_t
handshake_bitset,
};
constexpr std::string_view message_type_string(message_type type)
{
using namespace std::literals;
switch(type)
{
default:
case message_type::invalid: return "Invalid"sv;
case message_type::handshake: return "Handshake"sv;
case message_type::handshake_bitset: return "Handshake Bitset"sv;
}
}
struct message
{
message_type type;

View File

@ -6,10 +6,29 @@
#include <chrono>
namespace service_nodes {
constexpr auto PULSE_TIME_PER_BLOCK = std::chrono::minutes(2);
constexpr size_t PULSE_QUORUM_ENTROPY_LAG = 21; // How many blocks back from the tip of the Blockchain to source entropy for the Pulse quorums.
constexpr size_t PULSE_QUORUM_NUM_VALIDATORS = 11;
#if defined(LOKI_ENABLE_INTEGRATION_TEST_HOOKS)
constexpr auto PULSE_TIME_PER_BLOCK = std::chrono::seconds(5);
constexpr auto PULSE_WAIT_FOR_HANDSHAKES_DURATION = std::chrono::seconds(2);
constexpr auto PULSE_WAIT_FOR_OTHER_VALIDATOR_HANDSHAKES_DURATION = std::chrono::seconds(3);
constexpr size_t PULSE_QUORUM_NUM_VALIDATORS = 0;
constexpr size_t PULSE_BLOCK_REQUIRED_SIGNATURES = 0;
#else
constexpr auto PULSE_TIME_PER_BLOCK = std::chrono::minutes(2);
constexpr auto PULSE_WAIT_FOR_HANDSHAKES_DURATION = std::chrono::minutes(1);
constexpr auto PULSE_WAIT_FOR_OTHER_VALIDATOR_HANDSHAKES_DURATION = std::chrono::minutes(1);
constexpr size_t PULSE_QUORUM_NUM_VALIDATORS = 11;
constexpr size_t PULSE_BLOCK_REQUIRED_SIGNATURES = 7; // A block must have exactly N signatures to be considered properly
#endif
constexpr size_t PULSE_QUORUM_SIZE = PULSE_QUORUM_NUM_VALIDATORS + 1 /*Leader*/;
static_assert(PULSE_TIME_PER_BLOCK ==
PULSE_WAIT_FOR_HANDSHAKES_DURATION + PULSE_WAIT_FOR_OTHER_VALIDATOR_HANDSHAKES_DURATION);
static_assert(PULSE_QUORUM_NUM_VALIDATORS >= PULSE_BLOCK_REQUIRED_SIGNATURES);
static_assert(PULSE_QUORUM_ENTROPY_LAG >= PULSE_QUORUM_SIZE, "We need to pull atleast PULSE_QUORUM_SIZE number of blocks from the Blockchain, we can't if the amount of blocks to go back from the tip of the Blockchain is less than the blocks we need.");
constexpr size_t pulse_min_service_nodes(cryptonote::network_type nettype)
{
@ -26,10 +45,6 @@ namespace service_nodes {
return result;
}
constexpr size_t PULSE_BLOCK_REQUIRED_SIGNATURES = 7; // A block must have exactly N signatures to be considered properly
static_assert(PULSE_QUORUM_NUM_VALIDATORS >= PULSE_BLOCK_REQUIRED_SIGNATURES);
static_assert(PULSE_QUORUM_ENTROPY_LAG >= PULSE_QUORUM_SIZE, "We need to pull atleast PULSE_QUORUM_SIZE number of blocks from the Blockchain, we can't if the amount of blocks to go back from the tip of the Blockchain is less than the blocks we need.");
// Service node decommissioning: as service nodes stay up they earn "credits" (measured in blocks)
// towards a future outage. A new service node starts out with INITIAL_CREDIT, and then builds up
// CREDIT_PER_DAY for each day the service node remains active up to a maximum of