Skip to content

Latest commit

 

History

History

state_machine

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

State Machine Module

⚠️ Work in progress ⚠️ - At the time of writing this document, the architecture is still being defined.

This is pretty much a POC at the moment.

This document outlines the purpose of this module, its components and how they all interact with the other modules.

Contents

Overview

The StateMachine module implements a FSM (Finite State Machine) that is responsible for managing the node lifecycle since its internal behaviour can be different depending on certain conditions that are used to determine the current state.

In a nutshell: The FSM guarantees that the node is always in one specific state and verifies state transition (i.e. edges) to/from valid states (i.e. vertices).

Code Structure

├── docs
│   ├── CHANGELOG.md              # Changelog
│   ├── README.md                 # You are here
│   └── state-machine.diagram.md  # State machine diagram (generated by visualizer/main.go)
├── fsm.go                        # Finite State Machine definition (events, states, transitions)
├── module.go                     # Implementation of the StateMachine module
└── visualizer
    └── main.go                   # State machine diagram generator

High Level Architecture

High-level implementation details:

  • The github.com/looplab/fsm library is used to implement the FSM
  • Pocket builds a wrapper around looplab/fsm to integrate with the other modules
  • The StateMachineModule can be accessed via the bus from any other IntegratableModule
  • State machine transitions emit StateMachineTransitionEvent events that subscribed pocket modules can listen to
  • The node has a central event handler for events that fan-out event handling to the relevant modules during state transitions

FSM primer

The FSM has a declarative definition of an initial state and a set of transitions that have an Event, Source states and a single Destination state.

These are the main building blocks:

  • Event: An event is a string that represents an action that can trigger a transition. For example, the event start can be used to trigger a transition from the stopped state to the starting state.
  • State: A state is a string that represents a state that the FSM can be in. For example, the state stopped can be used to represent a state where the node is not running.
  • Callback: A callback is a function that is called when a transition occurs. For example, a callback can be used to log the transition or to perform some other action. Various types of callbacks essentially drive behaviour WHEN they are called and help build more complex behaviours like transition cancelling, etc. See the core FSM library documentation for more details.

State Machine States, Events and Lifecycle

Startup

  • Initialization: A node always starts in the Stopped state. Once it Starts, it transitions to P2P_Bootstrapping.
  • P2P Bootstrapping: The P2P module handles P2P_Bootstrapping -> fills the peer address book -> triggers a P2P_IsBootstrapped event -> transitions to P2P_Bootstrapped.

Consensus

  • P2P_Bootstrapped: The Consensus module handles P2P_Bootstrapped -> triggers a Consensus_IsUnsynced event -> transitions to Consensus_Unsynced.
  • Consensus_Unsynced: Node is out of sync, the Consensus module sends Consensus_IsSyncing event -> transitions to Consensus_SyncMode to start syncing with the rest of the network.
  • Consensus_SyncMode: The Consensus module runs StartSyncing() and requests blocks one by one from peers in its address book.
  • Node finishes syncing: When node completes syncing:
    • if the node is a validator, the Consensus module sends Consensus_IsSyncedValidator event -> transitions to Consensus_Pacemaker.
    • if the node is not a validator, the Consensus module sends Consensus_IsSyncedNonValidator event -> transitions to Consensus_Synced.
  • Consensus_Pacemaker: Node participates in the block generation process. If node receives a block proposal with height higher than its current height, the Consensus Module sends Consensus_IsUnsynced event -> transitions to Consensus_Unsynced.
  • Consensus_Synced: Currently, the Consensus module never sends Consensus_IsSyncedValidator event, and non-validator node always stays in Consensus_SyncMode.

A diagram of the current state machine definition can be found here.

NOTE: If you make changes to the state machine by changing states, events, or state transitions, you can re-generate the state machine diagram via:

make generate_node_state_machine_diagram