Consensus and DPoS
How TRON's 27 Super Representatives produce blocks under Delegated Proof of Stake, how blocks become irreversible, what happens at each 6-hour Maintenance Period boundary, how rewards are distributed, and how the consensus survives the realistic failure modes.
TRON uses Delegated Proof of Stake (DPoS) consensus. Twenty-seven Super Representatives (SRs), elected by stakers' votes, take turns producing blocks every 3 seconds. Blocks become irreversible — solidified — once at least 19 distinct active SRs have each produced a block at that height or above, typically in about 1 minute. Network parameters are themselves modifiable through on-chain proposals voted on by the SRs, which means consensus is also the network's governance loop.
This page covers the roles, the production schedule, fork choice, how blocks become final, what happens when SRs misbehave or the network degrades, how rewards flow, and how parameter changes propagate through the same consensus.
Prerequisites
At a glance
| Property | Value | Notes |
|---|---|---|
| Consensus algorithm | Delegated Proof of Stake (DPoS) | 27 elected producers, fixed schedule |
| Block time | 3 seconds | One slot = one scheduled SR |
| Round length | 81 seconds | 27 slots × 3 s, each active SR produces once per round |
| Active SRs | 27 | MAX_ACTIVE_WITNESS_NUM |
| Total ranked candidates | Top 127 | Active 27 + 100 SR Partners share voter rewards |
| Maintenance Period length | 6 hours | MAINTENANCE_TIME_INTERVAL, modifiable via proposal #0 |
| Maintenance pause at boundary | ~6 seconds | Two slots are skipped while the network re-ranks SRs |
| Solidification threshold | ≥19 distinct active SRs | Code uses SOLIDIFIED_THRESHOLD = 70 over active SR latestBlockNum values; with 27 active SRs, the result is 19 |
| Typical time to solidification | About 1 minute | User-visible Mainnet behavior during healthy block production. The code does not calculate solidification by counting down a fixed number of confirmations. |
| Block production reward | 8 TRX per block | Chain parameter #5 (getWitnessPayPerBlock) |
| Voter reward (shared by top 127) | 128 TRX per block | Chain parameter #31 (getWitness127PayPerBlock) |
| Mempool ordering | First-in-first-out | No auction-based MEV; no priority-fee bidding |
| Finality model | Threshold-based, deterministic | Once the solid height advances past a block, it does not roll back |
All numbers above are current chain-parameter values. They are themselves changeable by SR-voted proposal. Always query wallet/getchainparameters for the live values.
Vocabulary
The terms below are used consistently throughout this page and the rest of the consensus documentation. Several have parallels in other chains' consensus designs but with subtle TRON-specific meanings worth noting on first encounter.
| Term | Meaning |
|---|---|
| Super Representative (SR) | One of the 27 currently active block producers, elected by votes. Sometimes called witness in code (witness_address, WitnessCreateContract); the role and the protobuf field are the same thing. |
| SR Partner (SRP) | An account ranked 28th–127th by vote count. Cannot produce blocks, but earns voter rewards. |
| SR Candidate (SRC) | Any account that has registered as a block-producer candidate via WitnessCreateContract (paying a one-time, burned 9,999 TRX fee). Eligible to receive votes. |
| TRON Power (TP) | A non-transferable voting weight obtained by staking TRX (1 TRX staked = 1 TP). One TP authorizes one vote; staked balance = total votes the holder can cast. |
| Slot | A 3-second window during which one specific SR is scheduled to produce a block. If that SR fails, the slot is recorded as missed and the next slot belongs to the next SR. |
| Round | One full cycle of 27 consecutive slots. Within a round, each active SR has exactly one slot, in a fixed order derived from the vote tally at the start of the Maintenance Period. A round takes 81 seconds when no slots are missed. |
| Maintenance Period (MP) | The interval between two consecutive Maintenance Period boundaries — currently 6 hours (MAINTENANCE_TIME_INTERVAL, configurable by proposal). The active SR set, vote tallies, and brokerage values are all snapshotted per Maintenance Period. |
| Maintenance Period boundary | The moment between two consecutive Maintenance Periods when the network re-tallies votes, promotes the new top 27 into the active set, and processes any expired proposals. Block production pauses for ~6 seconds (two slot times) at this boundary. |
| Solidified block | A block for which at least 19 distinct active SRs have each produced a block at that height or above. The SolidityNode service indexes only these blocks. |
| Witness signature | The SR's signature over a block, written to the witness_signature field. Other nodes accept the block only if this signature is valid against the slot's expected SR (or its delegated witness_permission key). |
Roles
Three role tiers participate in consensus and the proposal system:
| Role | Vote rank | Active? | Can produce blocks | Can submit ProposalCreateContract | Can submit ProposalApproveContract | Approval counted at expiry | Voter reward |
|---|---|---|---|---|---|---|---|
| Active SR | Top 27 | Yes | Yes | Yes | Yes | Yes | Yes |
| SR Partner (SRP) | 28 – 127 | No | No | Yes | Yes (recorded but filtered out) | No | Yes |
| SR Candidate (SRC) | 128+ | No | No | Yes | Yes (recorded but filtered out) | No | No |
Any account can register as an SR Candidate by submitting a WitnessCreateContract, which burns a one-time 9,999 TRX application fee. The fee is sent to the network's black-hole address and cannot be reclaimed even if the account later stops being an SR — it functions as the network's Sybil-resistance gate for entering the producer pool.
Once registered, an SRC accumulates votes. At each Maintenance Period boundary the network re-ranks all SRCs by total votes received and promotes the top 27 into the active set for the next Maintenance Period; ranks 28–127 become SR Partners. An SR can move between active, partner, and pure candidate tiers from one Maintenance Period to the next based on real-time vote competition.
Super Representative terminologyThe role is called Super Representative in documentation prose. The contract type and storage fields use the legacy name (
WitnessCreateContract,witness_address,localwitness,--witness); these are kept in code for backward compatibility. Whenever you seewitness_*in API responses or config files, read it as "SR".
Election and active-set rotation
The DPoS election is continuous — there is no separate "election day". Votes accumulate in real time as accounts cast or revoke them, and the active set is recomputed at every Maintenance Period boundary from the latest tally.
How votes work
A vote is a non-transferable allocation of TRON Power (TP) from one account to one or more SR candidates. To vote, an account must first stake TRX through FreezeBalanceV2Contract, which gives 1 TP per 1 TRX staked. Voting is then performed by submitting a VoteWitnessContract transaction listing one or more candidates and the number of votes assigned to each. The total votes assigned must not exceed the account's staked TRX balance.
A VoteWitnessContract replaces the previous vote allocation in full — the entire votes list is rewritten on every call. To "remove" a vote for a specific SR, send a new VoteWitnessContract with a list that omits that SR.
Vote tallying at the Maintenance Period boundary
Votes change continuously, but the resulting active SR set is recomputed only at each Maintenance Period boundary. At that moment the network does the following, in order:
- Snapshot the per-cycle reward variable
Vifor every SR, which records the SR's effective vote weight for the just-ended Maintenance Period and is used later for voter reward calculation. - Apply pending vote deltas accumulated since the last boundary, updating each SR's running vote count.
- Re-rank all candidates by updated vote count.
- Promote the new top 27 to the active set, demote any falling below 27, and record the new role of every candidate.
- Snapshot brokerage values per SR for the new Maintenance Period.
Block production pauses for the two slot times following the boundary (~6 seconds total) while these steps execute. After the pause, the new active set begins producing in its newly computed slot order.
Effects of mid-cycle vote changes
Because the active set is fixed for the duration of a Maintenance Period, vote changes during a Maintenance Period do not change who produces blocks in that Maintenance Period. They only affect the next Maintenance Period. Voter rewards similarly attach to the vote allocation snapshotted at the previous Maintenance Period boundary — see Voting for SRs for the per-cycle snapshot semantics that explain how mid-cycle vote changes affect reward eligibility.
Block production schedule
A new block is produced every 3 seconds. Within each round of 27 slots, every active SR has exactly one slot, in a fixed order derived from the vote ranking at the start of the Maintenance Period. A round takes 81 seconds when every SR produces on schedule.
Slot order and rotation
The slot order is deterministic. SRs are sorted by vote count descending; the highest-voted SR receives the first slot of the round, the second-highest the second slot, and so on. The order does not change within a Maintenance Period, even as votes continue to shift. At the next Maintenance Period boundary, a new order is computed and the cycle restarts.
What happens inside a slot
When an SR's slot arrives, the SR:
-
Pulls transactions from its transaction mempool in the order it received them (FIFO).
-
Processes each transaction in a per-tx revoking session. Whether the transaction lands in the block depends on the contract type:
- System contracts (e.g.,
TransferContract,FreezeBalanceV2Contract,VoteWitnessContract,WitnessCreateContract): if the actuator'svalidate()orexecute()throws — invalid address, insufficient balance, account does not exist — the session is rolled back and the transaction is dropped from the block entirely. - Smart-contract calls (
TriggerSmartContract,CreateSmartContract): the transaction is included in the block whether the VM execution succeeds or reverts. A reverted call lands in the block with aFAILEDresult status; the Energy consumed (and any TRX burned to cover an Energy shortfall) is not refunded. This matches Ethereum-style semantics — failed contract calls are recorded on-chain because the caller has paid for the work.
Pre-execution failures common to both contract types — invalid signature, expired TAPOS reference, insufficient Bandwidth, transaction-too-large — also drop the transaction with no block inclusion.
- System contracts (e.g.,
-
Adds metadata: parent block ID, the SR's own address, the new block's height, and the block timestamp.
-
Signs the block with the configured
localwitnessprivate key. The signature lands in thewitness_signaturefield. -
Broadcasts the block to peers, who verify the signature, replay each included transaction (re-running validation and VM execution), and append the block to their local chain.
The included transactions appear in the block in the local node's mempool arrival order, not in a sender-paid priority order. There is no priority-fee mechanism — fee_limit is a per-transaction cap on Energy, not an inclusion bid. As a consequence, the auction-based MEV common on Ethereum (priority-fee gas wars, MEV-Boost validators sorting bundles by tip) does not exist on TRON.
Missed slots
If a scheduled SR fails to produce in its slot — common reasons include node downtime, network partition, or pre-upgrade drain — the slot is simply left empty. There is no replacement producer; the next slot proceeds at its scheduled time with the next SR. The empty slot does not delay subsequent slots.
A missed slot has two costs:
- The producing SR loses that block's 8 TRX block production reward. The entire 128 TRX voter reward pool for that slot is also forfeited because rewards are paid only for successful block production; every top-127 SR and its voters lose their proportional share for that slot.
- The network's average block time temporarily widens. After 1 missed slot in a round, the next block is 6 seconds later than scheduled instead of 3.
A persistently failing SR drops in voter confidence and typically loses votes, which moves it out of the active 27 at the next boundary. The network has no built-in slashing — the punishment for missed slots is economic (lost block rewards) and reputational (lost votes), not direct stake confiscation.
The Maintenance Period pause
At the end of each 6-hour Maintenance Period, block production pauses for two slot times (~6 seconds) while the network applies the vote tally, recomputes the active set, and snapshots brokerage values. The first block of the new Maintenance Period is produced approximately 6 seconds after the last block of the old Maintenance Period by the new top-ranked SR.
This pause is intentional and bounded — it is not a halt or stall. Clients should size their block-production-monitoring alert thresholds (e.g., "alert if no new block in 30 seconds") wide enough to absorb the pause without false positives.
Fork choice rule
A TRON peer can occasionally see two competing blocks at the chain tip — usually because of brief network delays, less commonly because an SR is equivocating. The rule it follows is short:
- Longest chain wins. A new block is only accepted if its height is strictly greater than the current head's height. Same-height alternatives are dropped without comparison.
- Ties resolved by first-seen. When a peer has already accepted block A at height H and a different block B also at height H arrives, B is dropped. There is no tie-break by block ID, signature, timestamp, or any other field — whichever block the peer processed first wins.
- Slot-level uniqueness. Each 3-second slot can produce at most one block on a peer's chain. The validity check
bSlot > hSlot(DposService.validBlock, line 128) rejects any block whose timestamp falls at or before the head's slot, even if it claims a different parent.
Walked example: two SRs see the chain in different orders
Suppose SR_A produces block 100 at slot N. Due to a transient network glitch, SR_B at slot N+1 hasn't received block 100 yet and produces block 100' (with parent = block 99 instead of block 100). Both blocks have height 100.
┌── 100 (by SR_A, slot N)
... 98 → 99 ─┤
└── 100' (by SR_B, slot N+1, didn't see 100)A peer that accepted 100 first now receives 100':
bSlot(100') = N+1,hSlot = N→bSlot > hSlotpasses.- But
getNum(100') = 100 == headerNumber→Manager.pushBlockreturns at line 1334. Block 100' is dropped.
Soon SR_C at slot N+2 produces block 101 — extending whichever block (100 or 100') it received first. As more SRs extend the same branch, that branch's height grows past the other:
┌── 100 ── 101 ── 102 ── ... (canonical, more SRs extending)
... 98 → 99 ─┤
└── 100' (orphaned, no successors)The losing branch is orphaned. Once at least 19 distinct active SRs have each produced a block at the fork-point height or above on the canonical branch, the fork is solidified out of reach.
Equivocation defense
If a single SR_X tries to sign two different blocks — A and B — at the same slot N, both blocks have:
- the same timestamp (and therefore the same
bSlot), - the same height,
- a valid signature from the scheduled SR (SR_X is the right producer for slot N),
so both pass the scheduledWitness check. The defense is the slot-uniqueness check at DposService.validBlock line 128: once one of A or B has been accepted as head, the other arrives with bSlot <= hSlot and is rejected.
A peer that received B first ends up on B; a peer that received A first ends up on A. The split is transient — only one of the two branches will accumulate further SR support, and the other is orphaned within roughly one round.
Producing out-of-turn (an SR signing a block at a slot scheduled for a different SR) is rejected by the scheduledWitness != witnessAddress check at line 141, so it cannot cause a fork in the first place.
How forks resolve
Forks at the tip of the chain typically resolve within one round (≤81 s) because:
- Block propagation among 27 well-connected SRs is sub-second on average.
- ≥19 active SRs will produce blocks on the same branch within their next 19 slots — at that point, the branch is solidified and forks below the new solidified height are no longer possible.
- An SR has a direct economic incentive to extend the canonical branch: 8 TRX of block reward is forfeit if the SR's block is later orphaned, and so is its share of the 128 TRX voter pool for that slot.
There is no automatic slashing for missed or equivocating blocks. StatisticManager.applyBlock increments a per-SR totalMissed counter for each empty slot, which voters can inspect via TronScan, but the protocol itself only enforces correctness through block rejection — not stake confiscation. Punishment for misbehavior is voter-driven: a misbehaving SR loses votes and falls out of the active 27 at the next Maintenance Period boundary.
Once a block has been solidified (next section), it is no longer subject to fork choice. The longest-chain rule applies only to unsolidified tip-of-chain blocks.
Block solidification
On the TRON network, each new block must wait for additional active Super Representatives (SRs) to keep extending the chain. Once at least 19 distinct active SRs (out of 27) have each produced a block at that height or above, the block is considered solidified — meaning it is final on-chain and cannot be replaced by a fork.
In practice, a new block typically becomes solidified in about 1 minute. The solid height only moves forward and never rolls back, which is why exchanges and wallets generally treat "block solidified" as the point of final settlement.
The threshold is set by the chain constant SOLIDIFIED_THRESHOLD = 70 (percent). The code does not hard-code 19. It sorts the active SRs' latestBlockNum values in ascending order, then picks the value at position size × (1 − threshold/100). With 27 active SRs, that position is 8:
int position = (int) (size * (1 - SOLIDIFIED_THRESHOLD * 1.0 / 100));
long newSolidNum = numbers.get(position);The value at index 8 is the 9th-smallest latestBlockNum. Indices 8 through 26 represent 19 distinct active SRs whose latest produced block is at height H or above, so height H becomes the new solidified height.
| Mechanism | Detail |
|---|---|
| Threshold | 19 of 27 active SRs on mainnet; derived from SOLIDIFIED_THRESHOLD = 70 and the active SR set size |
| What counts | An SR counts only when it has itself produced a block at height H or above on this chain |
| What gets solidified | The block at H and all earlier blocks |
| Typical time | About 1 minute once block production is healthy |
| Worst case | Bounded by the round length plus partition healing time |
| Where it's queryable | The SolidityNode service indexes only solidified data |
SR endorsement is implicit, not explicit.An SR contributes to solidification by producing a block at height H or above on the same chain. Receiving, forwarding, or merely linking through
parentHashdoes not contribute by itself. There is no separate "vote on this block" message.
For exchanges, bridges, and large-transfer confirmation logic, query the SolidityNode endpoint instead of the FullNode endpoint to ensure the data has been solidified.
Rewards
Each new block produces two reward streams paid in TRX:
| Reward | Recipient | Per block | Chain parameter |
|---|---|---|---|
| Block production reward | The SR producing the block | 8 TRX (8,000,000 sun) | #5 (getWitnessPayPerBlock) |
| Voter reward pool | Shared among the top 127 SRs by vote weight | 128 TRX (128,000,000 sun) | #31 (getWitness127PayPerBlock) |
Both reward values are governed by on-chain proposals. Query the current values at any time:
BASE_URL=https://api.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
POST ${BASE_URL}/wallet/getchainparametersIn the returned chainParameter array, look up entries by key — never by array index, since the array order does not match the proposal ID numbers.
Brokerage and voter share
Each SR sets a brokerage rate (default 20, range 0–100) that determines what share of the block production and voter rewards the SR retains before passing the rest to its voters. With a brokerage of 20 and a daily voter reward pool of 128 × 28800 ≈ 3.69M TRX (28,800 blocks per day at 3 s each), an SR that received 5% of the network's votes would:
- Retain 20% × 5% × 3.69M ≈ 36,900 TRX/day in its allowance balance.
- Pass through 80% × 5% × 3.69M ≈ 147,500 TRX/day for its voters to claim.
Voter reward claims are not automatic. Each voter calls WithdrawBalanceContract (max once per 24 hours) to move their accrued share into their spendable balance. Reward calculation uses a per-cycle snapshot of vote allocation; mid-cycle vote changes do not affect the current Maintenance Period's rewards. See Voting for SRs for the snapshot semantics and the at-most-one-claim-per-day rule.
Why voter rewards are spread over the top 127
The voter reward pool is split among the top 127 candidates (the 27 active SRs and the 100 SR Partners), proportional to the votes each received. SR Partners earn voter rewards even though they do not produce blocks. This design keeps healthy competition for SR slots — accounts that nearly miss the active 27 still earn enough to be worth running, which keeps a deep candidate pool ready to step in if any of the top 27 fails or loses votes.
The block production reward (8 TRX) goes only to the SR that actually produced the block — there is no analog for SR Partners, since they do not produce.
On-chain governance
Network parameters — block reward, resource pricing, TVM features, governance thresholds themselves — are not hard-coded. They live on-chain in a key-value store, and they are modifiable through proposals voted on by the active SRs.
A proposal goes through three phases tied to Maintenance Period boundaries:
- Submit — Any SR, SRP, or SRC submits a
ProposalCreateContractcarrying a map of{parameter_id: new_value}. The proposal voting window is controlled by chain parameter#92getProposalExpireTime, currently usually 3 days on Mainnet. - Vote — Until expiry, any SR / SRP / SRC may submit
ProposalApproveContractto add or withdraw an approval. All submissions are recorded on-chain; only approvals from the 27 currently active SRs at expiry are counted toward the threshold. - Tally and apply — At the expiration boundary, if ≥18 active-SR approvals are recorded, the proposal becomes
APPROVEDand its parameter changes are written to chain state in the same boundary block. If fewer, the proposal becomesDISAPPROVED. Either way the final state is permanently queryable.
The proposal-approval threshold (18) is distinct from the block-solidification threshold (19). The two mechanisms have related but different BFT bounds.
For the full lifecycle, vote-with-withdraw mechanics, committee rotation effects, and the canceling rule, see Committee & proposals. For the full list of modifiable parameters with current values, see Network parameters.
APIs
| API | Description |
|---|---|
wallet/getchainparameters | List all chain parameters and current values |
wallet/listwitnesses | List the active 27 SRs |
wallet/getnowblock | Latest block (FullNode) |
wallet/getblockbylimitnext | Range of blocks by height |
wallet/getnextmaintenancetime | Timestamp of the next Maintenance Period boundary |
walletsolidity/getnowblock | Latest solidified block (SolidityNode) |
wallet/proposalcreate | Submit a proposal |
wallet/proposalapprove | Approve an open proposal |
wallet/listproposals | List recent proposals and their states |
wallet/votewitnessaccount | Vote for one or more SRs (replaces the prior allocation) |
wallet/withdrawbalance | Claim accumulated voter rewards |
Related resources
- Super Representatives — How to apply, configure, and operate an SR node
- Committee & proposals — Full proposal lifecycle and committee rotation effects
- Network parameters — All proposable chain parameters
- Voting for SRs — Voter mechanics and reward-claim rules
- Blocks — Block structure, the composite block ID, and TAPOS reference
- Vote for Super Representatives — TronWeb recipe to cast votes and claim rewards
- Create a Governance Proposal — TronWeb recipe to submit and track a proposal
Updated about 15 hours ago