Pulse: Rename participation to validator_bitset

This commit is contained in:
Doyle 2020-08-05 17:32:18 +10:00
parent 72e57be95f
commit 601e9f77e1
8 changed files with 58 additions and 57 deletions

View File

@ -436,14 +436,14 @@ namespace cryptonote
struct pulse_header
{
pulse_random_value random_value;
uint8_t round;
uint16_t validator_participation_bits;
pulse_random_value random_value;
uint8_t round;
uint16_t validator_bitset;
BEGIN_SERIALIZE()
FIELD(random_value);
FIELD(round);
FIELD(validator_participation_bits);
FIELD(validator_bitset);
END_SERIALIZE();
};

View File

@ -16,7 +16,7 @@ enum struct round_state
wait_for_round,
round_starts,
wait_for_handshakes,
wait_for_other_validator_handshake_bitsets,
wait_for_handshake_bitsets,
submit_block_template,
wait_for_block_template,
terminate,
@ -32,7 +32,7 @@ constexpr std::string_view round_state_string(round_state state)
case round_state::wait_for_round: return "Wait For Round"sv;
case round_state::round_starts: return "Round Starts"sv;
case round_state::wait_for_handshakes: return "Wait For Handshakes"sv;
case round_state::wait_for_other_validator_handshake_bitsets: return "Wait For Validator Handshake Bitsets"sv;
case round_state::wait_for_handshake_bitsets: return "Wait For Validator Handshake Bitsets"sv;
case round_state::submit_block_template: return "Submit Block Template"sv;
case round_state::wait_for_block_template: return "Wait For Block Template"sv;
case round_state::terminate: return "Terminate"sv;
@ -69,11 +69,11 @@ struct round_context
struct
{
std::array<uint16_t, service_nodes::PULSE_QUORUM_NUM_VALIDATORS> received_bitsets;
int received_bitsets_count;
std::array<uint16_t, service_nodes::PULSE_QUORUM_NUM_VALIDATORS> bitsets;
int bitsets_count;
pulse::time_point end_time;
bool all_received() { return received_bitsets_count == service_nodes::PULSE_QUORUM_NUM_VALIDATORS; }
} wait_for_other_validator_handshake_bitsets;
bool all_received() { return bitsets_count == service_nodes::PULSE_QUORUM_NUM_VALIDATORS; }
} wait_for_handshake_bitsets;
struct
{
@ -325,8 +325,8 @@ void pump_messages_from_quorumnet(void *quorumnet_state, round_state round_state
pump_messages_until = context.wait_for_handshakes.end_time;
break;
case round_state::wait_for_other_validator_handshake_bitsets:
pump_messages_until = context.wait_for_other_validator_handshake_bitsets.end_time;
case round_state::wait_for_handshake_bitsets:
pump_messages_until = context.wait_for_handshake_bitsets.end_time;
break;
case round_state::wait_for_block_template:
@ -405,18 +405,18 @@ void pump_messages_from_quorumnet(void *quorumnet_state, round_state round_state
case pulse::message_type::handshake_bitset:
{
if (!msg_time_check(pulse_height, context, msg, pulse::clock::now(), context.wait_for_handshakes.start_time, context.wait_for_other_validator_handshake_bitsets.end_time))
if (!msg_time_check(pulse_height, context, msg, pulse::clock::now(), context.wait_for_handshakes.start_time, context.wait_for_handshake_bitsets.end_time))
continue;
uint16_t prev_bitset = context.wait_for_other_validator_handshake_bitsets.received_bitsets[msg.handshakes.quorum_position];
uint16_t prev_bitset = context.wait_for_handshake_bitsets.bitsets[msg.handshakes.quorum_position];
if (!context.round_starts.is_producer)
relay_message = (prev_bitset != msg.handshakes.validator_bitset);
context.wait_for_other_validator_handshake_bitsets.received_bitsets[msg.handshakes.quorum_position] = msg.handshakes.validator_bitset;
context.wait_for_handshake_bitsets.bitsets[msg.handshakes.quorum_position] = msg.handshakes.validator_bitset;
if (prev_bitset == 0)
context.wait_for_other_validator_handshake_bitsets.received_bitsets_count++;
context.wait_for_handshake_bitsets.bitsets_count++;
finish_pumping = context.wait_for_other_validator_handshake_bitsets.all_received();
finish_pumping = context.wait_for_handshake_bitsets.all_received();
}
break;
@ -449,10 +449,10 @@ void pump_messages_from_quorumnet(void *quorumnet_state, round_state round_state
continue;
}
if (block.pulse.validator_participation_bits != context.submit_block_template.validator_bitset)
if (block.pulse.validator_bitset != context.submit_block_template.validator_bitset)
{
auto block_bitset = std::bitset<sizeof(block.pulse.validator_participation_bits) * 8>(block.pulse.validator_participation_bits);
auto our_bitset = std::bitset<sizeof(block.pulse.validator_participation_bits) * 8>(context.submit_block_template.validator_bitset);
auto block_bitset = std::bitset<sizeof(block.pulse.validator_bitset) * 8>(block.pulse.validator_bitset);
auto our_bitset = std::bitset<sizeof(block.pulse.validator_bitset) * 8>(context.submit_block_template.validator_bitset);
MGINFO(log_prefix(pulse_height, context) << "Received pulse block template specifying different validator handshake bitsets " << block_bitset << ", expected " << our_bitset);
continue;
}
@ -595,8 +595,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 + 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;
context.wait_for_block_template.end_time = context.wait_for_other_validator_handshake_bitsets.end_time + service_nodes::PULSE_WAIT_FOR_BLOCK_TEMPLATE_DURATION;
context.wait_for_handshake_bitsets.end_time = context.wait_for_handshakes.end_time + service_nodes::PULSE_WAIT_FOR_OTHER_VALIDATOR_HANDSHAKES_DURATION;
context.wait_for_block_template.end_time = context.wait_for_handshake_bitsets.end_time + service_nodes::PULSE_WAIT_FOR_BLOCK_TEMPLATE_DURATION;
//
// NOTE: Quorum
@ -674,7 +674,7 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
{
context.round_starts.node_name = "W[0]";
MGINFO(log_prefix(pulse_height, context) << "We are the block producer for height " << pulse_height << " in round " << +context.wait_next_block.round << ", awaiting validator handshake bitsets.");
round_state = round_state::wait_for_other_validator_handshake_bitsets;
round_state = round_state::wait_for_handshake_bitsets;
}
}
else
@ -689,42 +689,42 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
case round_state::wait_for_handshakes:
{
assert(!context.round_starts.is_producer);
assert(context.round_starts.my_quorum_position < context.wait_for_other_validator_handshake_bitsets.received_bitsets.size());
assert(context.round_starts.my_quorum_position < context.wait_for_handshake_bitsets.bitsets.size());
bool timed_out = pulse::clock::now() >= context.wait_for_handshakes.end_time;
bool all_handshakes = context.wait_for_handshakes.all_received();
if (all_handshakes || timed_out)
{
assert(context.round_starts.my_quorum_position < context.wait_for_other_validator_handshake_bitsets.received_bitsets.size());
assert(context.round_starts.my_quorum_position < context.wait_for_handshake_bitsets.bitsets.size());
std::bitset<8 * sizeof(context.wait_for_handshakes.validator_bits)> bitset = context.wait_for_handshakes.validator_bits;
context.wait_for_other_validator_handshake_bitsets.received_bitsets[context.round_starts.my_quorum_position] = context.wait_for_handshakes.validator_bits;
context.wait_for_other_validator_handshake_bitsets.received_bitsets_count++;
context.wait_for_handshake_bitsets.bitsets[context.round_starts.my_quorum_position] = context.wait_for_handshakes.validator_bits;
context.wait_for_handshake_bitsets.bitsets_count++;
bool missing_handshakes = timed_out && !all_handshakes;
MGINFO(log_prefix(pulse_height, context) << "Collected validator handshakes " << bitset << (missing_handshakes ? ", we timed out and some handshakes were not seen! " : ". ") << "Sending handshake bitset and collecting other validator bitsets.");
try
{
cryptonote::quorumnet_send_pulse_validator_handshake_bitset(quorumnet_state, context.wait_for_round.quorum, top_hash, context.wait_for_handshakes.validator_bits);
round_state = round_state::wait_for_other_validator_handshake_bitsets;
round_state = round_state::wait_for_handshake_bitsets;
}
catch(std::exception const &e)
{
MERROR(log_prefix(pulse_height, context) << "Attempting to invoke and send a Pulse participation handshake bitset unexpectedly failed. " << e.what());
MERROR(log_prefix(pulse_height, context) << "Attempting to invoke and send a Pulse validator bitset unexpectedly failed. " << e.what());
round_state = thread_sleep(sleep_until::next_block_or_round, state, blockchain, context, pulse_mutex, pulse_height);
}
}
}
break;
case round_state::wait_for_other_validator_handshake_bitsets:
case round_state::wait_for_handshake_bitsets:
{
size_t const max_bitsets = context.wait_for_other_validator_handshake_bitsets.received_bitsets.size();
size_t const bitsets_count = context.wait_for_other_validator_handshake_bitsets.received_bitsets_count;
size_t const max_bitsets = context.wait_for_handshake_bitsets.bitsets.size();
size_t const bitsets_count = context.wait_for_handshake_bitsets.bitsets_count;
bool all_bitsets = context.wait_for_other_validator_handshake_bitsets.all_received();
bool timed_out = pulse::clock::now() >= context.wait_for_other_validator_handshake_bitsets.end_time;
bool all_bitsets = context.wait_for_handshake_bitsets.all_received();
bool timed_out = pulse::clock::now() >= context.wait_for_handshake_bitsets.end_time;
if (timed_out || all_bitsets)
{
bool missing_bitsets = timed_out && !all_bitsets;
@ -737,7 +737,7 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
int count = 0;
for (size_t validator_index = 0; validator_index < max_bitsets; validator_index++)
{
uint16_t bits = context.wait_for_other_validator_handshake_bitsets.received_bitsets[validator_index];
uint16_t bits = context.wait_for_handshake_bitsets.bitsets[validator_index];
uint16_t num = ++most_common_validator_bitset[bits];
if (num > count)
{
@ -810,8 +810,8 @@ 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;
block.pulse.round = context.wait_next_block.round;
block.pulse.validator_bitset = context.submit_block_template.validator_bitset;
std::string block_blob = cryptonote::t_serializable_object_to_blob(block);
crypto::hash hash = crypto::cn_fast_hash(block_blob.data(), block_blob.size());
@ -826,6 +826,7 @@ void pulse::main(pulse::state &state, void *quorumnet_state, cryptonote::core &c
case round_state::wait_for_block_template:
{
assert(!context.round_starts.is_producer);
bool timed_out = pulse::clock::now() >= context.wait_for_block_template.end_time;
if (timed_out || context.wait_for_block_template.received)
{

View File

@ -1242,13 +1242,13 @@ namespace service_nodes
static std::string dump_pulse_block_data(cryptonote::block const &block, service_nodes::quorum const *quorum)
{
std::stringstream stream;
std::bitset<8 * sizeof(block.pulse.validator_participation_bits)> const participation_bits = block.pulse.validator_participation_bits;
std::bitset<8 * sizeof(block.pulse.validator_bitset)> const validator_bitset = block.pulse.validator_bitset;
stream << "Block(" << cryptonote::get_block_height(block) << "): " << cryptonote::get_block_hash(block) << "\n";
stream << "Leader: ";
if (quorum) stream << (quorum->workers.empty() ? "(invalid leader)" : lokimq::to_hex(tools::view_guts(quorum->workers[0]))) << "\n";
else stream << "(invalid quorum)\n";
stream << "Round: " << +block.pulse.round << "\n";
stream << "Participating Validators: " << participation_bits << "\n";
stream << "Validator Bitset: " << validator_bitset << "\n";
stream << "Signatures: ";
if (block.signatures.empty()) stream << "(none)";
@ -1287,10 +1287,10 @@ namespace service_nodes
return false;
}
if (block.pulse.validator_participation_bits >= (1 << PULSE_QUORUM_NUM_VALIDATORS))
if (block.pulse.validator_bitset >= (1 << PULSE_QUORUM_NUM_VALIDATORS))
{
auto mask = std::bitset<sizeof(pulse_validator_bit_mask()) * 8>(pulse_validator_bit_mask());
LOG_PRINT_L1("Pulse block specifies validator participation bits out of bounds. Expected the bit mask " << mask << "\n" << dump_pulse_block_data(block, quorum.get()));
LOG_PRINT_L1("Pulse block specifies validator bitset out of bounds. Expected the bit mask " << mask << "\n" << dump_pulse_block_data(block, quorum.get()));
return false;
}
@ -1307,7 +1307,7 @@ namespace service_nodes
}
else
{
bool expect_pulse_quorum = (block.pulse.validator_participation_bits > 0 || block.signatures.size());
bool expect_pulse_quorum = (block.pulse.validator_bitset > 0 || block.signatures.size());
if (expect_pulse_quorum)
{
LOG_PRINT_L1("Failed to get pulse quorum for block\n" << dump_pulse_block_data(block, quorum.get()));

View File

@ -270,7 +270,7 @@ namespace service_nodes
}
auto const &block = reinterpret_cast<cryptonote::block const &>(context);
if (block.pulse.validator_participation_bits >= (1 << PULSE_QUORUM_NUM_VALIDATORS))
if (block.pulse.validator_bitset >= (1 << PULSE_QUORUM_NUM_VALIDATORS))
{
auto mask = std::bitset<sizeof(pulse_validator_bit_mask()) * 8>(pulse_validator_bit_mask());
LOG_PRINT_L1("Pulse block specifies validator participation bits out of bounds. Expected the bit mask: " << mask);
@ -304,7 +304,7 @@ namespace service_nodes
{
auto const block = std::any_cast<cryptonote::block const &>(context);
uint16_t bit = 1 << quorum_signature.voter_index;
if ((block.pulse.validator_participation_bits & bit) == 0)
if ((block.pulse.validator_bitset & bit) == 0)
{
LOG_PRINT_L1("Received pulse signature from validator " << static_cast<int>(quorum_signature.voter_index) << " that is not participating in round " << static_cast<int>(block.pulse.round));
return false;

View File

@ -812,7 +812,7 @@ bool loki_chain_generator::block_begin(loki_blockchain_entry &entry, loki_create
if (make_pulse_block)
{
// NOTE: Set up Pulse Header
blk.pulse.validator_participation_bits = service_nodes::pulse_validator_bit_mask(); // NOTE: Everyone participates
blk.pulse.validator_bitset = service_nodes::pulse_validator_bit_mask(); // NOTE: Everyone participates
blk.pulse.round = params.pulse_round;
for (size_t i = 0; i < sizeof(blk.pulse.random_value.data); i++)
blk.pulse.random_value.data[i] = static_cast<char>(tools::uniform_distribution_portable(tools::rng, 256));

View File

@ -148,7 +148,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(loki_service_nodes_insufficient_contribution);
GENERATE_AND_PLAY(loki_service_nodes_test_rollback);
GENERATE_AND_PLAY(loki_service_nodes_test_swarms_basic);
GENERATE_AND_PLAY(loki_pulse_invalid_participation_bits);
GENERATE_AND_PLAY(loki_pulse_invalid_validator_bitset);
GENERATE_AND_PLAY(loki_pulse_invalid_signature);
GENERATE_AND_PLAY(loki_pulse_oob_voter_index);
GENERATE_AND_PLAY(loki_pulse_non_participating_validator);

View File

@ -3051,19 +3051,19 @@ static loki_chain_generator setup_pulse_tests(std::vector<test_event_entry> &eve
return result;
}
bool loki_pulse_invalid_participation_bits::generate(std::vector<test_event_entry> &events)
bool loki_pulse_invalid_validator_bitset::generate(std::vector<test_event_entry> &events)
{
loki_chain_generator gen = setup_pulse_tests(events);
gen.add_event_msg("Invalid Block: Participation bits wrong");
gen.add_event_msg("Invalid Block: Validator bitset wrong");
loki_blockchain_entry entry = {};
loki_create_block_params params = gen.next_block_params();
gen.block_begin(entry, params, {} /*tx_list*/);
// NOTE: Overwrite participation bits to be wrong
entry.block.pulse.validator_participation_bits = ~service_nodes::pulse_validator_bit_mask();
// NOTE: Overwrite valiadator bitset to be wrong
entry.block.pulse.validator_bitset = ~service_nodes::pulse_validator_bit_mask();
gen.block_end(entry, params);
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong participation bits");
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong validator bitset");
return true;
}
@ -3079,7 +3079,7 @@ bool loki_pulse_invalid_signature::generate(std::vector<test_event_entry> &event
// NOTE: Overwrite signature
entry.block.signatures[0].signature = {};
gen.block_end(entry, params);
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong participation bits");
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong validator bitset");
return true;
}
@ -3095,7 +3095,7 @@ bool loki_pulse_oob_voter_index::generate(std::vector<test_event_entry> &events)
// NOTE: Overwrite oob voter index
entry.block.signatures.back().voter_index = service_nodes::PULSE_QUORUM_NUM_VALIDATORS + 1;
gen.block_end(entry, params);
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong participation bits");
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong validator bitset");
return true;
}
@ -3130,8 +3130,8 @@ bool loki_pulse_non_participating_validator::generate(std::vector<test_event_ent
// NOTE: First 7 validators are locked in. We received signatures from the
// first 6 in the quorum, then the 8th validator in the quorum (who is not
// meant to be participating).
entry.block.pulse.validator_participation_bits = 0b0000'000'0111'1111;
size_t const voter_indexes[] = {0, 1, 2, 3, 4, 5, 7};
entry.block.pulse.validator_bitset = 0b0000'000'0111'1111;
size_t const voter_indexes[] = {0, 1, 2, 3, 4, 5, 7};
crypto::hash block_hash = cryptonote::get_block_hash(entry.block);
for (size_t index : voter_indexes)
@ -3147,7 +3147,7 @@ bool loki_pulse_non_participating_validator::generate(std::vector<test_event_ent
}
gen.block_end(entry, params);
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong participation bits");
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "Invalid Pulse Block, specifies the wrong validator bitset");
return true;
}

View File

@ -77,7 +77,7 @@ struct loki_service_nodes_gen_nodes
struct loki_service_nodes_insufficient_contribution : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_service_nodes_test_rollback : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_service_nodes_test_swarms_basic : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_pulse_invalid_participation_bits : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_pulse_invalid_validator_bitset : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_pulse_invalid_signature : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_pulse_oob_voter_index : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_pulse_non_participating_validator : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };