Delay checkpoints by a block

Testnet has shown that it is virtually impossible to route around a
checkpoint for a block that had to be rendered unacceptable because it
accepts the future checkpoint which then prevents an alternate block
from being generated at all.

This mitigates it in two ways:

- Don't accept new checkpoint votes before we receive the block
- Delay checkpoint voting & vote distribution by one block (e.g. nodes
  will vote on block 12345 only once 12346 is received).

The first allows a manual pop_blocks to remove checkpoints that won't
get re-added (e.g. if the checkpointed block has become unacceptable, as
occurs sometimes in testnet/devnet, but could theoretically occur on
mainnet if we have to do a block reversal).

The second minimizes the number of rejected votes that will occur since
nodes will almost always have the block now when the checkpoint arrives.
This commit is contained in:
Jason Rhinelander 2022-04-17 12:48:39 -03:00
parent ef51e5dd63
commit f46884c5f1
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262
1 changed files with 3 additions and 4 deletions

View File

@ -460,7 +460,7 @@ namespace service_nodes
m_last_checkpointed_height = std::max(start_checkpointing_height, m_last_checkpointed_height);
for (;
m_last_checkpointed_height <= height;
m_last_checkpointed_height < height;
m_last_checkpointed_height += CHECKPOINT_INTERVAL)
{
uint8_t checkpointed_height_hf_version = get_network_version(m_core.get_nettype(), m_last_checkpointed_height);
@ -604,11 +604,10 @@ namespace service_nodes
std::unique_lock<cryptonote::Blockchain> lock{blockchain};
bool update_checkpoint;
bool update_checkpoint = false;
if (blockchain.get_checkpoint(vote.block_height, checkpoint) &&
checkpoint.block_hash == vote.checkpoint.block_hash)
{
update_checkpoint = false;
if (checkpoint.signatures.size() != service_nodes::CHECKPOINT_QUORUM_SIZE)
{
checkpoint.signatures.reserve(service_nodes::CHECKPOINT_QUORUM_SIZE);
@ -636,7 +635,7 @@ namespace service_nodes
}
}
}
else
else if (vote.block_height < core.get_current_blockchain_height()) // Don't accept checkpoints for blocks we don't have yet
{
update_checkpoint = true;
checkpoint = make_empty_service_node_checkpoint(vote.checkpoint.block_hash, vote.block_height);