After learning about the Basic concepts and Massa's node architecture, we have all the elements and vocabulary in place to explore the lifecycle of an operation within the network; from creation to permanent execution in a finalized block.
Operations originate externally from a client that is forging the operation, for example: a transaction or a smart contract code execution. The client will have to know the IP address of a Massa Node (this can be either because it is a node itself and will simply use localhost, or via some maintained list of known nodes and/or some browser plugin), and will then send the operation to the API.
When an operation is made available in a given node, it will be broadcasted to all other nodes via the Protocol/Network Module and to factories via the API Module, so that it will eventually end up in all the Pool Modules of the network.
Let’s assume we just got a code execution operation from an external client. Let’s suppose the client knows a particular node, which is running its block factory on the same machine, and sends the operation to this node. These are the different steps of the operation processing that will occur, as illustrated in the schema below:
The operation enters the node via the API Module (the operation path is marked in blue)
The API Module forwards the operation to the Pool Module and broadcasts it to other nodes via the Protocol/Network Module. Other nodes hearing about it will also broadcast it (gossip protocol), and feed it to their Pool Module.
At that stage, the operation sits in the Pool Modules of most nodes
The Selector Module elects a particular node to handle the block production of the next current slot
The elected node Block Factory finds out about its election by querying a Selector Module
It starts building a block by picking up pending operations in the Pool Module. The original operation is eventually picked and integrated into the block. It's worth to mention that only operations created by an address within the same thread as the block can be included. This is known as a 'transaction sharding' technique and it's used to prevent double spending problem. We will now follow the block around (the block path is marked in green)
The newly produced block is sent to the Graph/Consensus Module
The new block is processed by the Graph/Consensus Module to be included into the pending blocks DAG and potentially integrated into a new blockclique
The Graph/Consensus Module sends the new block to other nodes via the Protocol/Network Module, to ensure synchronization of the information in the network. The new block reaching other nodes is similarly going to be integrated into their Graph/Consensus Module
In general, the blockclique will be extended with the new block and so will reach the Execution Module from the Graph/Consensus Module via the notification of a new blockclique. Eventually, it will also be notified as a final block if it gets finalized.
The Execution Module will run the blocks that are part of the updated blockclique, so the original block will eventually be executed. Within the block is the original operation that was originally sent and that will then be applied to the ledger for potential modifications. At this stage, the modifications are not permanent and simply stored in a diff compared to the finalized ledger
Eventually, the block will be marked as final and the ledger modification, including the operation changes, will become final in the finalized ledger.