Conversation
auto itr = my->loaded_checkpoints.find( blk->block_num() ); | ||
if( itr != my->loaded_checkpoints.end() ) { | ||
auto id = blk->id(); | ||
EOS_ASSERT( itr->second == id, checkpoint_exception, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the future it would probably be convenient to allow for short-ids however, since we encode the block number in the ID we would need a canonical short ID that is reasonably collision resistant first.
CheckpointsThe DPOS consensus mechanism is designed to prevent two incompatible blocks from becoming final (irreversible) under the assumption of non-byzantine behavior by more than two-thirds of active block producers. Producers are economically disincentivized from byzantine behavior due to the fact that it is trivial to cryptographically prove byzantine behavior (double signing incompatible blocks) and because the likely consequences to a maliciously byzantine block producer is, at a start, loss of future block producer income. However, in the unlikely case that sufficient byzantine behavior occurs anyway, it is possible for there to a be fork in the blockchain that tricks newly synchronizing nodes to follow the blockchain down the "wrong branch" and get stuck there. In such scenarios, it is necessary for the node operators to manually intervene using trusted checkpoints they obtain from their social network in order to get back into consensus with the rest of the network. These checkpoints should be specified by the node operators and enforced by nodeos without any source code changes necessary. Specifying checkpointsCheckpoints can be specified in the config.ini file or via the command line in the form of Here is an example of two checkpoints on blocks 8 and 20 specified in the config.ini file:
Checkpoint enforcementCheckpoints are enforced during the operation of pushing a block onto the chain. This operation occurs as new blocks are considered during synchronization and normal operation of nodeos in which the blocks are discovered from the p2p network. The operation also occurs in the scenario in which blocks are explicitly pushed to nodeos via the chain API and the scenario in which the blocks are reapplied during replay. If a checkpoint that must be considered for a particular pushed block does not match the expected block ID, the block will be rejected by the push block operation by throwing a
|
Resolves #3337.
Added a new signal
pre_accepted_block
(as well as the corresponding channel which is not currently used) which is emitted fromcontroller_impl::push_block
prior to any stateful changes occurring in that function.Added a new class of exceptions that inherit from
controller_emit_signal_exception
. This class of exceptions is allowed to bubble out of theemit
call in controller. Anytime an exception which derives fromcontroller_emit_signal_exception
is used, we need to be careful that it being thrown does not cause the originatingemit
call to leavecontroller
in an inconsistent state.The new
checkpoint_exception
which does inherit fromcontroller_emit_signal_exception
is only potentially thrown from the synchronous signal handler ofpre_accepted_block
within chain_plugin. Therefore, it can only currently bubble up from theemit
call of thepre_accepted_block
signal incontroller_impl::push_block
which is safe since it does not leave things in an inconsistent state. All it does if thrown is reject the block that was trying to be pushed.This new exception is thrown if there is a mismatch between the block ID of the pushed block and the checkpoint block ID that may be set for that block number. The code to load this checkpoint information from the config or CLI options was already implemented prior to this PR.