Incorporate checkpoint validation into syncing step

Fix checkpoint verification check and add messages
This commit is contained in:
Doyle 2019-08-28 15:54:02 +10:00
parent 15ff209db0
commit 4724a7436f
14 changed files with 177 additions and 136 deletions

View File

@ -167,12 +167,12 @@ namespace cryptonote
return result;
}
//---------------------------------------------------------------------------
void checkpoints::block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs)
bool checkpoints::block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, checkpoint_t const *checkpoint)
{
uint64_t const height = get_block_height(block);
if (height < service_nodes::CHECKPOINT_STORE_PERSISTENTLY_INTERVAL ||
block.major_version < network_version_12_checkpointing)
return;
return true;
if (m_nettype == MAINNET && height == HF_VERSION_12_CHECKPOINTING_SOFT_FORK_HEIGHT)
{
@ -200,6 +200,9 @@ namespace cryptonote
}
}
if (checkpoint)
update_checkpoint(*checkpoint);
uint64_t end_cull_height = 0;
{
checkpoint_t immutable_checkpoint;
@ -229,6 +232,8 @@ namespace cryptonote
MERROR("Pruning block checkpoint on block added failed non-trivially at height: " << m_last_cull_height << ", what = " << e.what());
}
}
return true;
}
//---------------------------------------------------------------------------
void checkpoints::blockchain_detached(uint64_t height)

View File

@ -117,7 +117,7 @@ namespace cryptonote
public cryptonote::BlockchainDetachedHook
{
public:
void block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs) override;
bool block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, checkpoint_t const *checkpoint) override;
void blockchain_detached(uint64_t height) override;
bool get_checkpoint(uint64_t height, checkpoint_t &checkpoint) const;

View File

@ -39,7 +39,7 @@ namespace cryptonote {
class BlockAddedHook
{
public:
virtual void block_added(const block& block, const std::vector<transaction>& txs) = 0;
virtual bool block_added(const block& block, const std::vector<transaction>& txs, struct checkpoint_t const *checkpoint) = 0;
};
class BlockchainDetachedHook
@ -63,7 +63,7 @@ namespace cryptonote {
class AltBlockAddedHook
{
public:
virtual void alt_block_added(const block &block, const std::vector<transaction>& txs) = 0;
virtual bool alt_block_added(const block &block, const std::vector<transaction>& txs, struct checkpoint_t const *checkpoint) = 0;
};
/************************************************************************/
/* */

View File

@ -1124,7 +1124,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
for (auto& old_ch_ent : disconnected_chain)
{
block_verification_context bvc = boost::value_initialized<block_verification_context>();
bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc, false /*has_checkpoint*/);
bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc, nullptr /*checkpoint*/);
if(!r)
{
MERROR("Failed to push ex-main chain blocks to alternative chain ");
@ -1774,7 +1774,7 @@ bool Blockchain::build_alt_chain(const crypto::hash &prev_id, std::list<block_ex
// if that chain is long enough to become the main chain and re-org accordingly
// if so. If not, we need to hang on to the block in case it becomes part of
// a long forked chain eventually.
bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc, bool has_checkpoint)
bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc, checkpoint_t const *checkpoint)
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
@ -1899,20 +1899,9 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
}
bei.cumulative_difficulty += current_diff;
// add block to alternate blocks storage,
// as well as the current "alt chain" container
CHECK_AND_ASSERT_MES(!m_db->get_alt_block(id, NULL, NULL), false, "insertion of new alternative block returned as it already exists");
cryptonote::alt_block_data_t data;
data.height = bei.height;
data.cumulative_weight = bei.block_cumulative_weight;
data.cumulative_difficulty = bei.cumulative_difficulty;
data.already_generated_coins = bei.already_generated_coins;
m_db->add_alt_block(id, data, cryptonote::block_to_blob(bei.bl));
alt_chain.push_back(bei);
bool rejected_by_service_node = false;
bool is_a_checkpoint = false;
if(!has_checkpoint && !m_checkpoints.check_block(bei.height, id, &is_a_checkpoint, &rejected_by_service_node))
if(!checkpoint && !m_checkpoints.check_block(bei.height, id, &is_a_checkpoint, &rejected_by_service_node))
{
if (rejected_by_service_node && nettype() == MAINNET && block_height < HF_VERSION_12_CHECKPOINTING_SOFT_FORK_HEIGHT)
{
@ -1926,7 +1915,34 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
}
}
bool checkpointed = has_checkpoint || is_a_checkpoint;
{
std::vector<transaction> txs;
std::vector<crypto::hash> missed;
if (!get_transactions(b.tx_hashes, txs, missed))
{
bvc.m_verifivation_failed = true;
return false;
}
for (AltBlockAddedHook *hook : m_alt_block_added_hooks)
{
if (!hook->alt_block_added(b, txs, checkpoint))
return false;
}
}
// add block to alternate blocks storage,
// as well as the current "alt chain" container
CHECK_AND_ASSERT_MES(!m_db->get_alt_block(id, NULL, NULL), false, "insertion of new alternative block returned as it already exists");
cryptonote::alt_block_data_t data;
data.height = bei.height;
data.cumulative_weight = bei.block_cumulative_weight;
data.cumulative_difficulty = bei.cumulative_difficulty;
data.already_generated_coins = bei.already_generated_coins;
m_db->add_alt_block(id, data, cryptonote::block_to_blob(bei.bl));
alt_chain.push_back(bei);
bool checkpointed = checkpoint || is_a_checkpoint;
if (checkpointed || (main_chain_cumulative_difficulty < bei.cumulative_difficulty)) // check if difficulty bigger then in main chain
{
if (checkpointed)
@ -1956,17 +1972,6 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
}
else
{
std::vector<transaction> txs;
std::vector<crypto::hash> missed;
if (!get_transactions(b.tx_hashes, txs, missed))
{
bvc.m_verifivation_failed = true;
return false;
}
for (AltBlockAddedHook *hook : m_alt_block_added_hooks)
hook->alt_block_added(b, txs);
MGINFO_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "difficulty:\t" << current_diff);
return true;
}
@ -2625,7 +2630,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, block_verification_
{
LOG_PRINT_L3("Blockchain::" << __func__);
crypto::hash id = get_block_hash(bl);
return handle_block_to_main_chain(bl, id, bvc);
return handle_block_to_main_chain(bl, id, bvc, nullptr /*checkpoint*/);
}
//------------------------------------------------------------------
size_t Blockchain::get_total_transactions() const
@ -3675,7 +3680,7 @@ bool Blockchain::flush_txes_from_pool(const std::vector<crypto::hash> &txids)
// Needs to validate the block and acquire each transaction from the
// transaction mem_pool, then pass the block and transactions to
// m_db->add_block()
bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc)
bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc, checkpoint_t const *checkpoint)
{
LOG_PRINT_L3("Blockchain::" << __func__);
@ -4024,7 +4029,14 @@ leave:
only_txs.push_back(tx_pair.first);
for (BlockAddedHook* hook : m_block_added_hooks)
hook->block_added(bl, only_txs);
{
if (!hook->block_added(bl, only_txs, checkpoint))
{
MERROR("Block added hook signalled failure");
pop_block_from_blockchain();
return false;
}
}
TIME_MEASURE_FINISH(addblock);
@ -4220,22 +4232,19 @@ bool Blockchain::add_new_block(const block& bl, block_verification_context& bvc,
bool result = false;
rtxn_guard.stop();
//check that block refers to chain tail
if(!(bl.prev_id == get_tail_id()))
if(bl.prev_id == get_tail_id()) //check that block refers to chain tail
{
//chain switching or wrong block
bvc.m_added_to_main_chain = false;
result = handle_alternative_block(bl, id, bvc, (checkpoint != nullptr));
m_blocks_txs_check.clear();
//never relay alternative blocks
result = handle_block_to_main_chain(bl, id, bvc, checkpoint);
}
else
{
result = handle_block_to_main_chain(bl, id, bvc);
//chain switching or wrong block
bvc.m_added_to_main_chain = false;
result = handle_alternative_block(bl, id, bvc, checkpoint);
m_blocks_txs_check.clear();
//never relay alternative blocks
}
if (result && checkpoint)
update_checkpoint(*checkpoint);
return result;
}
//------------------------------------------------------------------

View File

@ -1224,7 +1224,7 @@ namespace cryptonote
*
* @return true if the block was added successfully, otherwise false
*/
bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc);
bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc, checkpoint_t const *checkpoint);
/**
* @brief validate and add a new block to an alternate blockchain
@ -1239,7 +1239,7 @@ namespace cryptonote
*
* @return true if the block was added successfully, otherwise false
*/
bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc, bool has_checkpoint);
bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc, checkpoint_t const *checkpoint);
/**
* @brief builds a list of blocks connecting a block to the main chain

View File

@ -713,9 +713,9 @@ namespace cryptonote
// Service Nodes
{
m_service_node_list.set_db_pointer(initialized_db);
m_service_node_list.set_quorum_history_storage(command_line::get_arg(vm, arg_store_quorum_history));
// NOTE: Implicit dependency. Service node list needs to be hooked before checkpoints.
m_blockchain_storage.hook_block_added(m_service_node_list);
m_blockchain_storage.hook_blockchain_detached(m_service_node_list);
m_blockchain_storage.hook_init(m_service_node_list);
@ -1662,25 +1662,7 @@ namespace cryptonote
// quorums are implemented and merged
if (checkpoint)
{
if (b->major_version >= network_version_13)
{
if (checkpoint->signatures.size() > 1)
{
for (size_t i = 0; i < (checkpoint->signatures.size() - 1); i++)
{
auto curr = checkpoint->signatures[i].voter_index;
auto next = checkpoint->signatures[i + 1].voter_index;
if (curr >= next)
{
LOG_PRINT_L1("Voters in checkpoints are not given in ascending order, block failed");
bvc.m_verifivation_failed = true;
return false;
}
}
}
}
else
if (b->major_version < network_version_13)
{
std::sort(checkpoint->signatures.begin(),
checkpoint->signatures.end(),

View File

@ -462,7 +462,10 @@ namespace service_nodes
auto it = state_history.find(state_change.block_height);
if (it == state_history.end())
{
LOG_PRINT_L1("Transaction: " << cryptonote::get_transaction_hash(tx) << ", references quorum at height: " << cryptonote::get_block_hash(block) << ", that is not stored");
return false;
}
quorum_manager const *quorums = &it->quorums;
cryptonote::tx_verification_context tvc = {};
@ -680,7 +683,7 @@ namespace service_nodes
return false;
}
static bool get_contribution(cryptonote::network_type nettype, int hard_fork_version, const cryptonote::transaction& tx, uint64_t block_height, parsed_tx_contribution &parsed_contribution)
static bool get_contribution(cryptonote::network_type nettype, int hf_version, const cryptonote::transaction& tx, uint64_t block_height, parsed_tx_contribution &parsed_contribution)
{
if (!cryptonote::get_service_node_contributor_from_tx_extra(tx.extra, parsed_contribution.address))
return false;
@ -1104,11 +1107,32 @@ namespace service_nodes
return false;
}
void service_node_list::block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs)
bool service_node_list::block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const *checkpoint)
{
if (block.major_version < cryptonote::network_version_9_service_nodes)
return true;
std::lock_guard<boost::recursive_mutex> lock(m_sn_mutex);
process_block(block, txs);
if (checkpoint)
{
std::shared_ptr<const testing_quorum> quorum = get_testing_quorum(quorum_type::checkpointing, checkpoint->height);
if (!quorum)
{
LOG_PRINT_L1("Failed to get testing quorum checkpoint for block: " << cryptonote::get_block_hash(block));
return false;
}
if (!service_nodes::verify_checkpoint(block.major_version, *checkpoint, *quorum))
{
LOG_PRINT_L1("Service node checkpoint failed verification for block: " << cryptonote::get_block_hash(block));
return false;
}
}
store();
return true;
}
static std::vector<size_t> generate_shuffled_service_node_index_list(
@ -1364,16 +1388,16 @@ namespace service_nodes
void service_node_list::process_block(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs)
{
uint64_t block_height = cryptonote::get_block_height(block);
int hard_fork_version = m_blockchain.get_hard_fork_version(block_height);
uint8_t hf_version = m_blockchain.get_hard_fork_version(block_height);
if (hard_fork_version < 9)
if (hf_version < 9)
return;
//
// Cull old history
//
{
uint64_t cull_height = short_term_state_cull_height(m_db, block_height);
uint64_t cull_height = short_term_state_cull_height(hf_version, m_db, block_height);
auto end_it = m_state_history.upper_bound(cull_height);
for (auto it = m_state_history.begin(); it != end_it; it++)
{
@ -1653,14 +1677,17 @@ namespace service_nodes
return true;
}
void service_node_list::alt_block_added(cryptonote::block const &block, std::vector<cryptonote::transaction> const &txs)
bool service_node_list::alt_block_added(cryptonote::block const &block, std::vector<cryptonote::transaction> const &txs, cryptonote::checkpoint_t const *checkpoint)
{
if (block.major_version < cryptonote::network_version_9_service_nodes)
return true;
uint64_t block_height = cryptonote::get_block_height(block);
state_t const *starting_state = nullptr;
crypto::hash const block_hash = get_block_hash(block);
auto it = m_alt_state.find(block_hash);
if (it != m_alt_state.end()) return; // NOTE: Already processed alt-state for this block
if (it != m_alt_state.end()) return true; // NOTE: Already processed alt-state for this block
// NOTE: Check if alt block forks off current state
if ((block_height == m_state.height) && (block.prev_id == m_state.block_hash))
@ -1681,24 +1708,48 @@ namespace service_nodes
if (it != m_alt_state.end()) starting_state = &it->second;
}
if (starting_state)
if (!starting_state)
{
if (starting_state->block_hash != block.prev_id)
{
LOG_PRINT_L1("Unexpected state_t's hash: " << starting_state->block_hash
<< ", does not match the block prev hash: " << block.prev_id);
return;
}
LOG_PRINT_L1("Received alt block but couldn't find parent state in historical state");
return false;
}
else
if (starting_state->block_hash != block.prev_id)
{
// TODO(loki): Fatal
return;
LOG_PRINT_L1("Unexpected state_t's hash: " << starting_state->block_hash
<< ", does not match the block prev hash: " << block.prev_id);
return false;
}
state_t alt_state = *starting_state;
alt_state.update_from_block(m_blockchain, m_state_history, m_alt_state, block, txs, m_service_node_pubkey);
m_alt_state[block_hash] = std::move(alt_state);
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);
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)
{
if (service_nodes::verify_checkpoint(block.major_version, *checkpoint, *alt_quorum))
{
verified_on_alt_quorum = true;
break;
}
}
if (!verified_on_alt_quorum)
return false;
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -2069,7 +2120,7 @@ namespace service_nodes
size_t const last_index = data_in.states.size() - 1;
for (size_t i = 0; i < last_index; i++)
{
state_serialized &entry = data_in.states[last_index];
state_serialized &entry = data_in.states[i];
if (entry.block_hash == crypto::null_hash) entry.block_hash = m_blockchain.get_block_id_by_height(entry.height);
m_state_history.emplace_hint(m_state_history.end(), std::move(entry));
}

View File

@ -35,7 +35,12 @@
#include "cryptonote_core/service_node_voting.h"
#include "cryptonote_core/service_node_quorum_cop.h"
namespace cryptonote { class Blockchain; class BlockchainDB; }
namespace cryptonote
{
class Blockchain;
class BlockchainDB;
struct checkpoint_t;
}; // namespace cryptonote
namespace service_nodes
{
@ -218,7 +223,7 @@ namespace service_nodes
}
}
using block_height = uint64_t;
using block_height = uint64_t;
class service_node_list
: public cryptonote::BlockAddedHook,
public cryptonote::BlockchainDetachedHook,
@ -228,11 +233,11 @@ namespace service_nodes
{
public:
service_node_list(cryptonote::Blockchain& blockchain);
void block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs) override;
bool block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const *checkpoint) override;
void blockchain_detached(uint64_t height) override;
void init() override;
bool validate_miner_tx(const crypto::hash& prev_id, const cryptonote::transaction& miner_tx, uint64_t height, int hard_fork_version, cryptonote::block_reward_parts const &base_reward) const override;
void alt_block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs) override;
bool alt_block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const *checkpoint) override;
std::vector<std::pair<cryptonote::account_public_address, uint64_t>> get_winner_addresses_and_portions() const;
crypto::public_key select_winner() const;

View File

@ -399,7 +399,7 @@ namespace service_nodes
}
}
void quorum_cop::block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs)
bool quorum_cop::block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const * /*checkpoint*/)
{
process_quorums(block);
@ -412,6 +412,7 @@ namespace service_nodes
m_vote_pool.remove_expired_votes(height);
m_vote_pool.remove_used_votes(txs, block.major_version);
return true;
}
bool quorum_cop::handle_vote(quorum_vote_t const &vote, cryptonote::vote_verification_context &vvc)
@ -438,7 +439,7 @@ namespace service_nodes
return false;
}
if (!verify_vote_against_quorum(vote, vvc, *quorum))
if (!verify_vote_signature(vote, vvc, *quorum))
return false;
std::vector<pool_vote_entry> votes = m_vote_pool.add_pool_vote_if_unique(vote, vvc);

View File

@ -39,6 +39,7 @@ namespace cryptonote
{
class core;
struct vote_verification_context;
struct checkpoint_t;
};
namespace service_nodes
@ -81,7 +82,7 @@ namespace service_nodes
explicit quorum_cop(cryptonote::core& core);
void init() override;
void block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs) override;
bool block_added(const cryptonote::block& block, const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const * /*checkpoint*/) override;
void blockchain_detached(uint64_t height) override;
void set_votes_relayed (std::vector<quorum_vote_t> const &relayed_votes);

View File

@ -238,37 +238,56 @@ namespace service_nodes
return true;
}
bool verify_checkpoint(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::testing_quorum const &quorum)
{
if (checkpoint.type == cryptonote::checkpoint_type::service_node)
{
if ((checkpoint.height % service_nodes::CHECKPOINT_INTERVAL) != 0)
{
LOG_PRINT_L1("Checkpoint given but not expecting a checkpoint at height: " << checkpoint.height);
return false;
}
if (checkpoint.signatures.size() < service_nodes::CHECKPOINT_MIN_VOTES)
{
LOG_PRINT_L1("Checkpoint has insufficient signatures to be considered");
LOG_PRINT_L1("Checkpoint has insufficient signatures to be considered at height: " << checkpoint.height);
return false;
}
if (checkpoint.signatures.size() > service_nodes::CHECKPOINT_QUORUM_SIZE)
{
LOG_PRINT_L1("Checkpoint has too many signatures to be considered");
LOG_PRINT_L1("Checkpoint has too many signatures to be considered at height: " << checkpoint.height);
return false;
}
std::array<size_t, service_nodes::CHECKPOINT_QUORUM_SIZE> unique_vote_set = {};
for (service_nodes::voter_to_signature const &voter_to_signature : checkpoint.signatures)
for (size_t i = 0; i < checkpoint.signatures.size(); i++)
{
service_nodes::voter_to_signature const &voter_to_signature = checkpoint.signatures[i];
if (hf_version >= cryptonote::network_version_13 && i < (checkpoint.signatures.size() - 1))
{
auto curr = checkpoint.signatures[i].voter_index;
auto next = checkpoint.signatures[i + 1].voter_index;
if (curr >= next)
{
LOG_PRINT_L1("Voters in checkpoints are not given in ascending order, checkpoint failed verification at height: " << checkpoint.height);
return false;
}
}
if (!bounds_check_worker_index(quorum, voter_to_signature.voter_index, nullptr)) return false;
crypto::public_key const &key = quorum.workers[voter_to_signature.voter_index];
if (unique_vote_set[voter_to_signature.voter_index]++)
{
LOG_PRINT_L1("Voter quorum index is duplicated: " << voter_to_signature.voter_index);
LOG_PRINT_L1("Voter: " << epee::string_tools::pod_to_hex(key) << ", quorum index is duplicated: " << voter_to_signature.voter_index << ", checkpoint failed verification at height: " << checkpoint.height);
return false;
}
crypto::public_key const &key = quorum.workers[voter_to_signature.voter_index];
if (!crypto::check_signature(checkpoint.block_hash, key, voter_to_signature.signature))
{
LOG_PRINT_L1("Invalid signatures for votes");
LOG_PRINT_L1("Invalid signatures for votes, checkpoint failed verification at height: " << checkpoint.height << " for voter: " << epee::string_tools::pod_to_hex(key));
return false;
}
}
@ -277,7 +296,7 @@ namespace service_nodes
{
if (checkpoint.signatures.size() != 0)
{
LOG_PRINT_L1("Non service-node checkpoints should have no signatures");
LOG_PRINT_L1("Non service-node checkpoints should have no signatures, checkpoint failed at height: " << checkpoint.height);
return false;
}
}
@ -326,7 +345,7 @@ namespace service_nodes
return result;
}
bool verify_vote_against_quorum(const quorum_vote_t &vote, cryptonote::vote_verification_context &vvc, const service_nodes::testing_quorum &quorum)
bool verify_vote_signature(const quorum_vote_t &vote, cryptonote::vote_verification_context &vvc, const service_nodes::testing_quorum &quorum)
{
bool result = true;
if (vote.type >= quorum_type::count)

View File

@ -103,10 +103,10 @@ namespace service_nodes
quorum_vote_t make_state_change_vote(uint64_t block_height, uint16_t index_in_group, uint16_t worker_index, new_state state, crypto::public_key const &pub_key, crypto::secret_key const &secret_key);
bool verify_checkpoint (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::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_vote_age (const quorum_vote_t& vote, uint64_t latest_height, cryptonote::vote_verification_context &vvc);
bool verify_vote_against_quorum (const quorum_vote_t& vote, cryptonote::vote_verification_context &vvc, const service_nodes::testing_quorum &quorum);
bool verify_vote_signature (const quorum_vote_t& vote, cryptonote::vote_verification_context &vvc, const service_nodes::testing_quorum &quorum);
crypto::signature make_signature_from_vote (quorum_vote_t const &vote, const crypto::public_key& pub, const crypto::secret_key& sec);
crypto::signature make_signature_from_tx_state_change(cryptonote::tx_extra_service_node_state_change const &state_change, crypto::public_key const &pub, crypto::secret_key const &sec);

View File

@ -1317,39 +1317,7 @@ namespace cryptonote
return false;
}
checkpoint = &checkpoint_allocated_on_stack_;
bool maybe_has_checkpoint = (checkpoint->height % service_nodes::CHECKPOINT_INTERVAL == 0);
if (!maybe_has_checkpoint)
{
MERROR("Checkpoint blob given but not expecting a checkpoint at this height");
return false;
}
// TODO(doyle): If we are receiving alternative blocks, we won't
// have the quorum for the alternative chain meaning we will not
// be able to verify the checkpoint. For now always accept
// whatever checkpoint we receive
#if 1
std::vector<std::shared_ptr<const service_nodes::testing_quorum>> alt_states;
std::shared_ptr<const service_nodes::testing_quorum> quorum = m_core.get_testing_quorum(
service_nodes::quorum_type::checkpointing, checkpoint->height, false /*include_old*/, &alt_states);
if (!quorum)
{
MERROR("Failed to get service node quorum for height: "
<< checkpoint->height
<< ", quorum should be available as we are syncing the chain and deriving the current "
"relevant quorum");
return false;
}
// TODO(doyle): add reasoning, important for sync failures
if (!service_nodes::verify_checkpoint(*checkpoint, *quorum))
{
MERROR("Failed to verify checkpoint at height: " << checkpoint->height);
return false;
}
#endif
checkpoint = &checkpoint_allocated_on_stack_;
}
// process block

View File

@ -125,7 +125,7 @@ static bool verify_vote(service_nodes::quorum_vote_t const &vote,
service_nodes::testing_quorum const &quorum)
{
bool result = service_nodes::verify_vote_age(vote, latest_height, vvc);
result &= service_nodes::verify_vote_against_quorum(vote, vvc, quorum);
result &= service_nodes::verify_vote_signature(vote, vvc, quorum);
return result;
}