Purpose and Scope
This page describes the full flow by which a StableNet node produces and mines blocks.It covers the role of the worker, block candidate assembly, transaction selection and execution, and the process of submitting the generated block to the consensus engine (WBFT) for finalization.
For details on the WBFT consensus protocol itself, including voting, BLS signature aggregation, and epoch management, see Anzeon WBFT Consensus Protocol.
Worker Architecture
Theworker is the core component responsible for block production in StableNet.It selects and executes transactions from the transaction pool, assembles blocks, and submits completed block candidates to the consensus engine for sealing.
Worker Structure
The worker maintains multiple goroutines to process each stage of block production in parallel.| Component | Goroutine | Purpose |
|---|---|---|
mainLoop | Yes | Handles work requests and events, coordinates block assembly |
newWorkLoop | Yes | Triggers block creation based on chain events or consensus signals |
taskLoop | Yes | Submits assembled blocks to the consensus engine |
resultLoop | Yes | Receives sealed blocks and writes them to the chain |
current *environment: Execution environment of the block currently being assembledcoinbase common.Address: Block producer address (validator address)tip *uint256.Int: Minimum gas tip required for transaction inclusionpendingTasks map[common.Hash]*task: Block tasks awaiting sealingtxsCh,chainHeadCh,readyToCommitCh: Channels for transactions, chain head updates, and consensus signals
Worker Initialization
When Anzeon mode is enabled, the worker initializes by reading the network-wide gas tip from the GovValidator contract.Afterward, each time a new block is added to the chain, a callback is triggered to re-read the latest gas tip and update internal state and transaction pool filtering criteria.
Block Production Flow
WBFT vs Origin Work Loop
StableNet uses different block production strategies depending on whether the consensus engine is WBFT.- Origin (Ethereum default): Attempts new blocks periodically based on a timer
- WBFT: Starts block production only when the consensus engine emits a
readyToCommitChsignal
WBFT Ready-to-Commit Mechanism
The WBFT engine requests block production via thereadyToCommit(round) callback.The
round value indicates the current consensus round, where round = 0 is the initial attempt and round > 0 represents retries after previous failures.
Block Assembly Process
Main Loop and Commit Work
mainLoop() receives consensus signals or chain events and then invokes commitWork(), which performs the actual block assembly.This function sequentially creates the block header, prepares the execution environment, and executes transactions.
prepareWork – Block Header Setup
prepareWork() prepares the header and execution environment for a new block.
Steps
- Select parent block: Choose the latest chain head or a specified parent
- Timestamp validation: Adjust to ensure the timestamp is later than the parent block
- Header creation: Initialize base header fields via
makeHeader() - Environment setup: Create state snapshot and gas pool via
makeEnv() - Engine preparation: Call
engine.Prepare()to set consensus-specific fields, including proposer and coinbase for WBFT
Transaction Selection and Execution
fillTransactions() selects transactions from the transaction pool that are eligible for inclusion in the current block.Selection is based on gas tip, nonce ordering, and per-account validity checks.
commitTransactions – Execution Loop
commitTransactions() executes the selected transactions sequentially.
- On
ErrNonceTooLow, the transaction is skipped and the next nonce transaction for the same account is attempted - On successful execution, a receipt is recorded and execution proceeds to the next transaction
- On fatal errors, all subsequent transactions from the same account are excluded
applyTransaction – State Transition
Each transaction is applied to the state viaapplyTransaction().
- Create a pre-execution state snapshot
- Execute EVM logic and apply state changes via
core.ApplyTransaction() - Revert to the snapshot on failure
- On success, add the transaction and receipt to the block
core.ApplyTransaction().
Block Finalization
Once all transactions are executed, the block enters the finalization phase.In a WBFT environment, since there are no block rewards,
Finalize() performs minimal work, mainly computing the state root and receipt root.
Sealing and Result Handling
Task Submission Loop
taskLoop() submits completed blocks to the consensus engine.
- WBFT: The block is passed to the consensus engine, initiating PREPARE and COMMIT voting
- Other engines: Engine-specific sealing logic is executed
resultCh.
Result Handling Loop
resultLoop() receives sealed blocks and writes them to the chain.
- Set block hash, block number, and transaction index in receipts
- Persist the block and state root to the database
- In Anzeon mode, re-query the GovValidator contract after block insertion to refresh the gas tip
Transaction Filtering and Gas Tip Handling
Gas Tip Handling in Anzeon
In the Anzeon network, gas tips are not individually configured by validators but are globally managed by governance (GovValidator).updateGasTipFromContract() reads the contract state and updates the minimum gas tip requirement for both the worker and the transaction pool.
This ensures:
- Only transactions paying sufficient gas tips are included in block candidates
- Gas tip changes take effect immediately from the next block
- The transaction pool proactively filters out transactions below the required threshold
Transaction Prioritization
Transactions are ordered using thetransactionsByPriceAndNonce structure.
Priority Rules
- Local transactions first
- Effective gas price:
min(gasTipCap + baseFee, gasFeeCap) - Nonce ordering: Sequential processing within each account
- Cross-account price comparison: Higher effective gas price first
Environment and State Management
Execution Environment
Theenvironment structure holds all execution state required during block assembly.
| Field | Purpose |
|---|---|
signer types.Signer | Transaction signature verification |
state *state.StateDB | State trie |
tcount int | Number of transactions in the block |
gasPool *core.GasPool | Remaining gas limit |
header *types.Header | Header of the block being built |
txs []*types.Transaction | Included transactions |
receipts []*types.Receipt | Execution receipts |
makeEnv(), which prepares a state copy based on the parent block and initializes the gas pool.
State Changes and Commit
State changes are managed in the following order.- Modify StateDB through transaction execution
- Roll back using snapshots when necessary
- Commit state to the trie after successful block sealing
- Persist the block and state root to the database
updateSnapshot() maintains the pending block state to support RPC calls such as eth_getBlockByNumber("pending").
Integration with Miner Wrapper
TheMiner type wraps the worker and controls block production based on node synchronization status.Block production is paused during chain synchronization and automatically resumed once synchronization completes.
Summary Flow
The block production process can be summarized as follows.- Consensus engine or chain event triggers block production
- Worker prepares the block header and execution environment
- Transactions are selected and executed
- The block is finalized and submitted to the consensus engine
- After sealing, the block is written to the chain and gas tips are synchronized

