#engine #consensus #clique #block #state #vapory #defined

vapcore-clique

Vapory style clique consensus engine

Show the crate…

2 unstable releases

0.1.0 Mar 8, 2021
0.0.0 Mar 7, 2021

#18 in #vapory


Used in 10 crates (via vapcore-spec)

GPL-3.0 license

2.5MB
12K SLoC

vapcore-clique

Implementation of the Clique PoA Engine.

File structure:

  • mod.rs -> Provides the engine API implementation, with additional block state tracking
  • block_state.rs -> Records the Clique state for given block.
  • params.rs -> Contains the parameters for the Clique engine.
  • step_service.rs -> An event loop to trigger sealing.
  • util.rs -> Various standalone utility functions.
  • tests.rs -> Consensus tests as defined in EIP-225.

How syncing works:

  1. Client will call:
    • Clique::verify_block_basic()
    • Clique::verify_block_unordered()
    • Clique::verify_block_family()
  2. Using Clique::state() we try and retrieve the parent state. If this isn't found we need to back-fill it from the last known checkpoint.
  3. Once we have a good state, we can record it using CliqueBlockState::apply().

How sealing works:

  1. Set a signer using Engine::set_signer(). If a miner account was set up through a config file or CLI flag MinerService::set_author() will eventually set the signer
  2. We check that the engine is ready for sealing through Clique::sealing_state() Note: This is always SealingState::Ready for Clique
  3. Calling Clique::new() will spawn a StepService thread. This thread will call Engine::step() periodically. Internally, the Clique step() function calls Client::update_sealing(), which is what makes and seals a block.
  4. Clique::generate_seal() will then be called by miner. This will return a Seal which is either a Seal::None or Seal:Regular. The following shows how a Seal variant is chosen: a. We return Seal::None if no signer is available or the signer is not authorized. b. If period == 0 and block has transactions, we return Seal::Regular, otherwise return Seal::None. c. If we're INTURN, wait for at least period since last block before trying to seal. d. If we're not INTURN, we wait for a random amount of time using the algorithm specified in EIP-225 before trying to seal again.
  5. Miner will create new block, in process it will call several engine methods to do following: a. Clique::open_block_header_timestamp() must set timestamp correctly. b. Clique::populate_from_parent() must set difficulty to correct value. Note: Clique::populate_from_parent() is used in both the syncing and sealing code paths.
  6. We call Clique::on_seal_block() which will allow us to modify the block header during seal generation.
  7. Finally, Clique::verify_local_seal() is called. After this, the syncing code path will be followed in order to import the new block.

Dependencies

~27MB
~418K SLoC