mirror of https://github.com/oxen-io/oxen-core.git
Rename `testing_quorum` class to just `quorum`
testing_quorum is a bit of a misnomer: it only does testing when used for an obligations quorum, but it is also used for checkpointing and soon Blink.
This commit is contained in:
parent
4706f86d84
commit
1b5234e6a6
|
@ -3211,7 +3211,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|||
}
|
||||
|
||||
auto const quorum_type = service_nodes::quorum_type::obligations;
|
||||
auto const quorum = m_service_node_list.get_testing_quorum(quorum_type, state_change.block_height);
|
||||
auto const quorum = m_service_node_list.get_quorum(quorum_type, state_change.block_height);
|
||||
{
|
||||
if (!quorum)
|
||||
{
|
||||
|
|
|
@ -2254,9 +2254,9 @@ namespace cryptonote
|
|||
return si.available;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
std::shared_ptr<const service_nodes::testing_quorum> core::get_testing_quorum(service_nodes::quorum_type type, uint64_t height, bool include_old, std::vector<std::shared_ptr<const service_nodes::testing_quorum>> *alt_states) const
|
||||
std::shared_ptr<const service_nodes::quorum> core::get_quorum(service_nodes::quorum_type type, uint64_t height, bool include_old, std::vector<std::shared_ptr<const service_nodes::quorum>> *alt_states) const
|
||||
{
|
||||
return m_service_node_list.get_testing_quorum(type, height, include_old, alt_states);
|
||||
return m_service_node_list.get_quorum(type, height, include_old, alt_states);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::is_service_node(const crypto::public_key& pubkey, bool require_active) const
|
||||
|
|
|
@ -798,7 +798,7 @@ namespace cryptonote
|
|||
* @param include_old whether to look in the old quorum states (does nothing unless running with --store-full-quorum-history)
|
||||
* @return Null shared ptr if quorum has not been determined yet or is not defined for height
|
||||
*/
|
||||
std::shared_ptr<const service_nodes::testing_quorum> get_testing_quorum(service_nodes::quorum_type type, uint64_t height, bool include_old = false, std::vector<std::shared_ptr<const service_nodes::testing_quorum>> *alt_states = nullptr) const;
|
||||
std::shared_ptr<const service_nodes::quorum> get_quorum(service_nodes::quorum_type type, uint64_t height, bool include_old = false, std::vector<std::shared_ptr<const service_nodes::quorum>> *alt_states = nullptr) const;
|
||||
|
||||
/**
|
||||
* @brief Get a non owning reference to the list of blacklisted key images
|
||||
|
|
|
@ -209,7 +209,7 @@ namespace service_nodes
|
|||
return sort_and_filter(service_nodes_infos, [](const service_node_info &info) { return info.is_decommissioned() && info.is_fully_funded(); }, /*reserve=*/ false);
|
||||
}
|
||||
|
||||
std::shared_ptr<const testing_quorum> service_node_list::get_testing_quorum(quorum_type type, uint64_t height, bool include_old, std::vector<std::shared_ptr<const testing_quorum>> *alt_quorums) const
|
||||
std::shared_ptr<const quorum> service_node_list::get_quorum(quorum_type type, uint64_t height, bool include_old, std::vector<std::shared_ptr<const quorum>> *alt_quorums) const
|
||||
{
|
||||
height = offset_testing_quorum_height(type, height);
|
||||
std::lock_guard<boost::recursive_mutex> lock(m_sn_mutex);
|
||||
|
@ -251,17 +251,17 @@ namespace service_nodes
|
|||
state_t const &alt_state = hash_to_state.second;
|
||||
if (alt_state.height == height)
|
||||
{
|
||||
std::shared_ptr<const testing_quorum> alt_result = alt_state.quorums.get(type);
|
||||
std::shared_ptr<const quorum> alt_result = alt_state.quorums.get(type);
|
||||
if (alt_result) alt_quorums->push_back(alt_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<const testing_quorum> result = quorums->get(type);
|
||||
std::shared_ptr<const quorum> result = quorums->get(type);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool get_pubkey_from_quorum(testing_quorum const &quorum, quorum_group group, size_t quorum_index, crypto::public_key &key)
|
||||
static bool get_pubkey_from_quorum(quorum const &quorum, quorum_group group, size_t quorum_index, crypto::public_key &key)
|
||||
{
|
||||
std::vector<crypto::public_key> const *array = nullptr;
|
||||
if (group == quorum_group::validator) array = &quorum.validators;
|
||||
|
@ -284,7 +284,7 @@ namespace service_nodes
|
|||
|
||||
bool service_node_list::get_quorum_pubkey(quorum_type type, quorum_group group, uint64_t height, size_t quorum_index, crypto::public_key &key) const
|
||||
{
|
||||
std::shared_ptr<const testing_quorum> quorum = get_testing_quorum(type, height);
|
||||
std::shared_ptr<const quorum> quorum = get_quorum(type, height);
|
||||
if (!quorum)
|
||||
{
|
||||
LOG_PRINT_L1("Quorum for height: " << height << ", was not stored by the daemon");
|
||||
|
@ -1132,7 +1132,7 @@ namespace service_nodes
|
|||
|
||||
if (block.major_version >= cryptonote::network_version_13_enforce_checkpoints && checkpoint)
|
||||
{
|
||||
std::shared_ptr<const testing_quorum> quorum = get_testing_quorum(quorum_type::checkpointing, checkpoint->height);
|
||||
std::shared_ptr<const quorum> quorum = get_quorum(quorum_type::checkpointing, checkpoint->height);
|
||||
if (!quorum)
|
||||
{
|
||||
LOG_PRINT_L1("Failed to get testing quorum checkpoint for block: " << cryptonote::get_block_hash(block));
|
||||
|
@ -1211,7 +1211,7 @@ namespace service_nodes
|
|||
{
|
||||
auto type = static_cast<quorum_type>(type_int);
|
||||
size_t num_validators = 0, num_workers = 0;
|
||||
auto quorum = std::make_shared<testing_quorum>();
|
||||
auto quorum = std::make_shared<service_nodes::quorum>();
|
||||
std::vector<size_t> pub_keys_indexes;
|
||||
|
||||
if (type == quorum_type::obligations)
|
||||
|
@ -1734,15 +1734,15 @@ namespace service_nodes
|
|||
|
||||
if (checkpoint)
|
||||
{
|
||||
std::vector<std::shared_ptr<const service_nodes::testing_quorum>> alt_quorums;
|
||||
std::shared_ptr<const testing_quorum> quorum = get_testing_quorum(quorum_type::checkpointing, checkpoint->height, false, &alt_quorums);
|
||||
std::vector<std::shared_ptr<const service_nodes::quorum>> alt_quorums;
|
||||
std::shared_ptr<const quorum> quorum = get_quorum(quorum_type::checkpointing, checkpoint->height, false, &alt_quorums);
|
||||
if (!quorum)
|
||||
return false;
|
||||
|
||||
if (!service_nodes::verify_checkpoint(block.major_version, *checkpoint, *quorum))
|
||||
{
|
||||
bool verified_on_alt_quorum = false;
|
||||
for (std::shared_ptr<const service_nodes::testing_quorum> alt_quorum : alt_quorums)
|
||||
for (std::shared_ptr<const service_nodes::quorum> alt_quorum : alt_quorums)
|
||||
{
|
||||
if (service_nodes::verify_checkpoint(block.major_version, *checkpoint, *alt_quorum))
|
||||
{
|
||||
|
@ -2092,17 +2092,11 @@ namespace service_nodes
|
|||
static quorum_manager quorum_for_serialization_to_quorum_manager(service_node_list::quorum_for_serialization const &source)
|
||||
{
|
||||
quorum_manager result = {};
|
||||
{
|
||||
auto quorum = std::make_shared<testing_quorum>(source.quorums[static_cast<uint8_t>(quorum_type::obligations)]);
|
||||
result.obligations = quorum;
|
||||
}
|
||||
result.obligations = std::make_shared<quorum>(source.quorums[static_cast<uint8_t>(quorum_type::obligations)]);
|
||||
|
||||
// Don't load any checkpoints that shouldn't exist (see the comment in generate_quorums as to why the `+BUFFER` term is here).
|
||||
if ((source.height + REORG_SAFETY_BUFFER_BLOCKS_POST_HF12) % CHECKPOINT_INTERVAL == 0)
|
||||
{
|
||||
auto quorum = std::make_shared<testing_quorum>(source.quorums[static_cast<uint8_t>(quorum_type::checkpointing)]);
|
||||
result.checkpointing = quorum;
|
||||
}
|
||||
result.checkpointing = std::make_shared<quorum>(source.quorums[static_cast<uint8_t>(quorum_type::checkpointing)]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -324,8 +324,8 @@ namespace service_nodes
|
|||
/// the actual internal quorum used is for `height - REORG_SAFETY_BUFFER_BLOCKS_POST_HF12`, i.e.
|
||||
/// do no subtract off the buffer in advance)
|
||||
/// return: nullptr if the quorum is not cached in memory (pruned from memory).
|
||||
std::shared_ptr<const testing_quorum> get_testing_quorum(quorum_type type, uint64_t height, bool include_old = false, std::vector<std::shared_ptr<const testing_quorum>> *alt_states = nullptr) const;
|
||||
bool get_quorum_pubkey(quorum_type type, quorum_group group, uint64_t height, size_t quorum_index, crypto::public_key &key) const;
|
||||
std::shared_ptr<const quorum> get_quorum(quorum_type type, uint64_t height, bool include_old = false, std::vector<std::shared_ptr<const quorum>> *alt_states = nullptr) const;
|
||||
bool get_quorum_pubkey(quorum_type type, quorum_group group, uint64_t height, size_t quorum_index, crypto::public_key &key) const;
|
||||
|
||||
std::vector<service_node_pubkey_info> get_service_node_list_state(const std::vector<crypto::public_key> &service_node_pubkeys) const;
|
||||
const std::vector<key_image_blacklist_entry> &get_blacklisted_key_images() const { return m_state.key_image_blacklist; }
|
||||
|
@ -363,7 +363,7 @@ namespace service_nodes
|
|||
{
|
||||
uint8_t version;
|
||||
uint64_t height;
|
||||
testing_quorum quorums[static_cast<uint8_t>(quorum_type::count)];
|
||||
quorum quorums[static_cast<uint8_t>(quorum_type::count)];
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(version)
|
||||
|
|
|
@ -253,15 +253,14 @@ namespace service_nodes
|
|||
// don't vote for the first 2 hours so this is purely cosmetic
|
||||
if (obligations_height_hf_version >= cryptonote::network_version_12_checkpointing)
|
||||
{
|
||||
service_nodes::quorum_type checkpoint_type = quorum_type::checkpointing;
|
||||
std::shared_ptr<const testing_quorum> quorum = m_core.get_testing_quorum(checkpoint_type, m_obligations_height);
|
||||
auto quorum = m_core.get_quorum(quorum_type::checkpointing, m_obligations_height);
|
||||
std::vector<cryptonote::block> blocks;
|
||||
if (quorum && m_core.get_blocks(m_obligations_height, 1, blocks))
|
||||
{
|
||||
cryptonote::block const &block = blocks[0];
|
||||
if (start_time < static_cast<ptrdiff_t>(block.timestamp)) // NOTE: If we started up before receiving the block, we likely have the voting information, if not we probably don't.
|
||||
{
|
||||
uint64_t quorum_height = offset_testing_quorum_height(checkpoint_type, m_obligations_height);
|
||||
uint64_t quorum_height = offset_testing_quorum_height(quorum_type::checkpointing, m_obligations_height);
|
||||
for (size_t index_in_quorum = 0; index_in_quorum < quorum->validators.size(); index_in_quorum++)
|
||||
{
|
||||
crypto::public_key const &key = quorum->validators[index_in_quorum];
|
||||
|
@ -282,7 +281,7 @@ namespace service_nodes
|
|||
if (!my_keys)
|
||||
continue;
|
||||
|
||||
std::shared_ptr<const testing_quorum> quorum = m_core.get_testing_quorum(quorum_type::obligations, m_obligations_height);
|
||||
auto quorum = m_core.get_quorum(quorum_type::obligations, m_obligations_height);
|
||||
if (!quorum)
|
||||
{
|
||||
// TODO(loki): Fatal error
|
||||
|
@ -437,7 +436,7 @@ namespace service_nodes
|
|||
if (m_last_checkpointed_height < REORG_SAFETY_BUFFER_BLOCKS)
|
||||
continue;
|
||||
|
||||
const std::shared_ptr<const testing_quorum> quorum = m_core.get_testing_quorum(quorum_type::checkpointing, m_last_checkpointed_height);
|
||||
auto quorum = m_core.get_quorum(quorum_type::checkpointing, m_last_checkpointed_height);
|
||||
if (!quorum)
|
||||
{
|
||||
// TODO(loki): Fatal error
|
||||
|
@ -479,7 +478,7 @@ namespace service_nodes
|
|||
if (!verify_vote_age(vote, m_core.get_current_blockchain_height(), vvc))
|
||||
return false;
|
||||
|
||||
std::shared_ptr<const testing_quorum> quorum = m_core.get_testing_quorum(vote.type, vote.block_height);
|
||||
std::shared_ptr<const quorum> quorum = m_core.get_quorum(vote.type, vote.block_height);
|
||||
if (!quorum)
|
||||
{
|
||||
vvc.m_invalid_block_height = true;
|
||||
|
|
|
@ -46,10 +46,10 @@ namespace service_nodes
|
|||
{
|
||||
struct service_node_info;
|
||||
|
||||
struct testing_quorum
|
||||
struct quorum
|
||||
{
|
||||
std::vector<crypto::public_key> validators; // Array of public keys identifying service nodes which are being tested for the queried height.
|
||||
std::vector<crypto::public_key> workers; // Array of public keys identifying service nodes which are responsible for voting on the queried height.
|
||||
std::vector<crypto::public_key> validators; // Array of public keys identifying service nodes who validate and sign.
|
||||
std::vector<crypto::public_key> workers; // Array of public keys of tested service nodes (if applicable).
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(validators)
|
||||
|
@ -59,12 +59,12 @@ namespace service_nodes
|
|||
|
||||
struct quorum_manager
|
||||
{
|
||||
std::shared_ptr<const testing_quorum> obligations;
|
||||
// TODO(doyle): Validators aren't used, but I kept this as a testing_quorum
|
||||
std::shared_ptr<const quorum> obligations;
|
||||
// TODO(doyle): Workers aren't used, but I kept this as a quorum
|
||||
// to avoid drastic changes for now to a lot of the service node API
|
||||
std::shared_ptr<const testing_quorum> checkpointing;
|
||||
std::shared_ptr<const quorum> checkpointing;
|
||||
|
||||
std::shared_ptr<const testing_quorum> get(quorum_type type) const
|
||||
std::shared_ptr<const quorum> get(quorum_type type) const
|
||||
{
|
||||
if (type == quorum_type::obligations) return obligations;
|
||||
else if (type == quorum_type::checkpointing) return checkpointing;
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace service_nodes {
|
|||
#endif
|
||||
|
||||
static_assert(STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE <= STATE_CHANGE_QUORUM_SIZE, "The number of votes required to kick can't exceed the actual quorum size, otherwise we never kick.");
|
||||
static_assert(CHECKPOINT_MIN_VOTES <= CHECKPOINT_QUORUM_SIZE, "The number of votes required to kick can't exceed the actual quorum size, otherwise we never kick.");
|
||||
static_assert(CHECKPOINT_MIN_VOTES <= CHECKPOINT_QUORUM_SIZE, "The number of votes required to add a checkpoint can't exceed the actual quorum size, otherwise we never add checkpoints.");
|
||||
|
||||
// NOTE: We can reorg up to last 2 checkpoints + the number of extra blocks before the next checkpoint is set
|
||||
constexpr uint64_t REORG_SAFETY_BUFFER_BLOCKS_POST_HF12 = (CHECKPOINT_INTERVAL * CHECKPOINT_NUM_CHECKPOINTS_FOR_CHAIN_FINALITY) + (CHECKPOINT_INTERVAL - 1);
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace service_nodes
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool bounds_check_worker_index(service_nodes::testing_quorum const &quorum, uint32_t worker_index, cryptonote::vote_verification_context *vvc)
|
||||
static bool bounds_check_worker_index(service_nodes::quorum const &quorum, uint32_t worker_index, cryptonote::vote_verification_context *vvc)
|
||||
{
|
||||
if (worker_index >= quorum.workers.size())
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ namespace service_nodes
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool bounds_check_validator_index(service_nodes::testing_quorum const &quorum, uint32_t validator_index, cryptonote::vote_verification_context *vvc)
|
||||
static bool bounds_check_validator_index(service_nodes::quorum const &quorum, uint32_t validator_index, cryptonote::vote_verification_context *vvc)
|
||||
{
|
||||
if (validator_index >= quorum.validators.size())
|
||||
{
|
||||
|
@ -133,7 +133,7 @@ namespace service_nodes
|
|||
bool verify_tx_state_change(const cryptonote::tx_extra_service_node_state_change &state_change,
|
||||
uint64_t latest_height,
|
||||
cryptonote::tx_verification_context &tvc,
|
||||
const service_nodes::testing_quorum &quorum,
|
||||
const service_nodes::quorum &quorum,
|
||||
const uint8_t hf_version)
|
||||
{
|
||||
auto &vvc = tvc.m_vote_ctx;
|
||||
|
@ -232,7 +232,7 @@ namespace service_nodes
|
|||
return true;
|
||||
}
|
||||
|
||||
bool verify_checkpoint(uint8_t hf_version, cryptonote::checkpoint_t const &checkpoint, service_nodes::testing_quorum const &quorum)
|
||||
bool verify_checkpoint(uint8_t hf_version, cryptonote::checkpoint_t const &checkpoint, service_nodes::quorum const &quorum)
|
||||
{
|
||||
if (checkpoint.type == cryptonote::checkpoint_type::service_node)
|
||||
{
|
||||
|
@ -359,7 +359,7 @@ namespace service_nodes
|
|||
return result;
|
||||
}
|
||||
|
||||
bool verify_vote_signature(uint8_t hf_version, const quorum_vote_t &vote, cryptonote::vote_verification_context &vvc, const service_nodes::testing_quorum &quorum)
|
||||
bool verify_vote_signature(uint8_t hf_version, const quorum_vote_t &vote, cryptonote::vote_verification_context &vvc, const service_nodes::quorum &quorum)
|
||||
{
|
||||
bool result = true;
|
||||
if (vote.type >= quorum_type::count)
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace cryptonote
|
|||
|
||||
namespace service_nodes
|
||||
{
|
||||
struct testing_quorum;
|
||||
struct quorum;
|
||||
|
||||
struct checkpoint_vote { crypto::hash block_hash; };
|
||||
struct state_change_vote { uint16_t worker_index; new_state state; };
|
||||
|
@ -116,10 +116,10 @@ namespace service_nodes
|
|||
quorum_vote_t make_checkpointing_vote(uint8_t hf_version, crypto::hash const &block_hash, uint64_t block_height, uint16_t index_in_quorum, const service_node_keys &keys);
|
||||
cryptonote::checkpoint_t make_empty_service_node_checkpoint(crypto::hash const &block_hash, uint64_t height);
|
||||
|
||||
bool verify_checkpoint (uint8_t hf_version, cryptonote::checkpoint_t const &checkpoint, service_nodes::testing_quorum const &quorum);
|
||||
bool verify_tx_state_change (const cryptonote::tx_extra_service_node_state_change& state_change, uint64_t latest_height, cryptonote::tx_verification_context& vvc, const service_nodes::testing_quorum &quorum, uint8_t hf_version);
|
||||
bool verify_checkpoint (uint8_t hf_version, cryptonote::checkpoint_t const &checkpoint, service_nodes::quorum const &quorum);
|
||||
bool verify_tx_state_change (const cryptonote::tx_extra_service_node_state_change& state_change, uint64_t latest_height, cryptonote::tx_verification_context& vvc, const service_nodes::quorum &quorum, uint8_t hf_version);
|
||||
bool verify_vote_age (const quorum_vote_t& vote, uint64_t latest_height, cryptonote::vote_verification_context &vvc);
|
||||
bool verify_vote_signature (uint8_t hf_version, const quorum_vote_t& vote, cryptonote::vote_verification_context &vvc, const service_nodes::testing_quorum &quorum);
|
||||
bool verify_vote_signature (uint8_t hf_version, const quorum_vote_t& vote, cryptonote::vote_verification_context &vvc, const service_nodes::quorum &quorum);
|
||||
crypto::signature make_signature_from_vote (quorum_vote_t const &vote, const service_node_keys &keys);
|
||||
crypto::signature make_signature_from_tx_state_change(cryptonote::tx_extra_service_node_state_change const &state_change, const service_node_keys &keys);
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#include "tx_blink.h"
|
||||
#include "common/util.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace cryptonote {
|
||||
|
||||
static void check_args(blink_tx::quorum q, unsigned position, const char *func_name) {
|
||||
if (q >= blink_tx::quorum::_count)
|
||||
throw std::domain_error("Invalid sub-quorum value passed to " + std::string(func_name));
|
||||
if (position >= BLINK_QUORUM_SIZE)
|
||||
throw std::domain_error("Invalid voter position passed to " + std::string(func_name));
|
||||
}
|
||||
|
||||
crypto::public_key get_sn_pubkey(blink_tx::quorum q, unsigned position) {
|
||||
check_args(q, position, __func__);
|
||||
// TODO
|
||||
return crypto::null_pkey;
|
||||
};
|
||||
|
||||
crypto::hash blink_tx::hash() const {
|
||||
auto buf = tools::memcpy_le(height_, tx_.hash);
|
||||
crypto::hash hash;
|
||||
crypto::cn_fast_hash(buf.data(), buf.size(), hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool blink_tx::add_signature(quorum q, unsigned position, const crypto::signature &sig) {
|
||||
check_args(q, position, __func__);
|
||||
|
||||
auto &sig_slot = signatures_[static_cast<uint8_t>(q)][position];
|
||||
if (sig_slot && sig_slot == sig)
|
||||
return false;
|
||||
|
||||
if (!crypto::check_signature(hash(), get_sn_pubkey(q, position), sig))
|
||||
throw signature_verification_error("Given blink quorum signature verification failed!");
|
||||
|
||||
sig_slot = sig;
|
||||
}
|
||||
|
||||
bool blink_tx::has_signature(quorum q, unsigned position) {
|
||||
check_args(q, position, __func__);
|
||||
return signatures_[static_cast<uint8_t>(q)][position];
|
||||
}
|
||||
|
||||
bool blink_tx::valid() const {
|
||||
// Signatures are verified when added, so here we can just test that they are non-null
|
||||
return std::all_of(signatures_.begin(), signatures_.end(), [](const auto &sigs) {
|
||||
return BLOCK_QUORUM_VOTES_REQUIRED <= std::count_if(sigs.begin(), sigs.end(),
|
||||
[](const auto &s) -> bool { return s; });
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2019, The Loki Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../cryptonote_basic/cryptonote_basic.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace cryptonote {
|
||||
|
||||
constexpr unsigned int BLINK_QUORUM_SIZE = 10;
|
||||
constexpr unsigned int BLOCK_QUORUM_VOTES_REQUIRED = 7;
|
||||
|
||||
class blink_tx {
|
||||
public:
|
||||
enum class quorum : uint8_t { base, future, _count };
|
||||
|
||||
class signature_verification_error : public std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a new blink_tx wrapper given the tx and a blink authorization height.
|
||||
*/
|
||||
blink_tx(transaction tx, uint64_t height)
|
||||
: tx_{std::move(tx)}, height_{height} {}
|
||||
|
||||
/**
|
||||
* Adds a signature for the given quorum and position. Returns true if the signature was accepted
|
||||
* (i.e. is valid, and existing signature is empty), false if the signature was already present,
|
||||
* and throws a `blink_tx::signature_verification_error` if the signature fails validation.
|
||||
*/
|
||||
bool add_signature(quorum q, unsigned int position, const crypto::signature &sig);
|
||||
|
||||
/**
|
||||
* Remove the signature at the given quorum and position by setting it to null. Returns true if
|
||||
* removed, false if it was already null.
|
||||
*/
|
||||
bool clear_signature(quorum q, unsigned int position);
|
||||
|
||||
/**
|
||||
* Returns true if there is a verified signature at the given quorum and position.
|
||||
*/
|
||||
bool has_signature(quorum q, unsigned int position);
|
||||
|
||||
/**
|
||||
* Returns true if this blink tx is valid for inclusion in the blockchain, that is, has the
|
||||
* required number of valid signatures in each quorum.
|
||||
*/
|
||||
bool valid() const;
|
||||
|
||||
/// Returns a reference to the transaction.
|
||||
const transaction &tx() const { return tx_; }
|
||||
|
||||
/// Returns the blink authorization height of this blink tx
|
||||
uint64_t height() const { return height_; }
|
||||
|
||||
/// Returns the hashed signing value for this blink TX (a fast hash of the height + tx hash)
|
||||
crypto::hash hash() const;
|
||||
|
||||
private:
|
||||
transaction tx_;
|
||||
uint64_t height_;
|
||||
std::array<std::array<crypto::signature, BLINK_QUORUM_SIZE>, static_cast<uint8_t>(quorum::_count)> signatures_;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -183,7 +183,7 @@ static quorum_vote_t deserialize_vote(const bt_dict &d) {
|
|||
return vote;
|
||||
}
|
||||
|
||||
static const std::vector<crypto::public_key> &quorum_voter_list(quorum_type t, const service_nodes::testing_quorum &q) {
|
||||
static const std::vector<crypto::public_key> &quorum_voter_list(quorum_type t, const service_nodes::quorum &q) {
|
||||
return t == quorum_type::checkpointing ? q.workers : q.validators;
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ static void relay_votes(void *obj, const std::vector<service_nodes::quorum_vote_
|
|||
std::vector<std::tuple<int, const service_nodes::quorum_vote_t *, const std::vector<crypto::public_key> *>> valid_votes;
|
||||
valid_votes.reserve(votes.size());
|
||||
for (auto &v : votes) {
|
||||
auto quorum = snw.sn_list.get_testing_quorum(v.type, v.block_height);
|
||||
auto quorum = snw.sn_list.get_quorum(v.type, v.block_height);
|
||||
|
||||
if (!quorum) {
|
||||
MWARNING("Unable to relay vote: no testing quorum vote for type " << v.type << " @ height " << v.block_height);
|
||||
|
|
|
@ -2585,7 +2585,7 @@ namespace cryptonote
|
|||
for (int quorum_int = (int)start_quorum_iterator; quorum_int <= (int)end_quorum_iterator; quorum_int++)
|
||||
{
|
||||
auto type = static_cast<service_nodes::quorum_type>(quorum_int);
|
||||
if (std::shared_ptr<const service_nodes::testing_quorum> quorum = m_core.get_testing_quorum(type, height, true /*include_old*/))
|
||||
if (std::shared_ptr<const service_nodes::quorum> quorum = m_core.get_quorum(type, height, true /*include_old*/))
|
||||
{
|
||||
COMMAND_RPC_GET_QUORUM_STATE::quorum_for_height entry = {};
|
||||
entry.height = height;
|
||||
|
|
Loading…
Reference in New Issue