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

PropertyValueNotes
Consensus algorithmDelegated Proof of Stake (DPoS)27 elected producers, fixed schedule
Block time3 secondsOne slot = one scheduled SR
Round length81 seconds27 slots × 3 s, each active SR produces once per round
Active SRs27MAX_ACTIVE_WITNESS_NUM
Total ranked candidatesTop 127Active 27 + 100 SR Partners share voter rewards
Maintenance Period length6 hoursMAINTENANCE_TIME_INTERVAL, modifiable via proposal #0
Maintenance pause at boundary~6 secondsTwo slots are skipped while the network re-ranks SRs
Solidification threshold≥19 distinct active SRsCode uses SOLIDIFIED_THRESHOLD = 70 over active SR latestBlockNum values; with 27 active SRs, the result is 19
Typical time to solidificationAbout 1 minuteUser-visible Mainnet behavior during healthy block production. The code does not calculate solidification by counting down a fixed number of confirmations.
Block production reward8 TRX per blockChain parameter #5 (getWitnessPayPerBlock)
Voter reward (shared by top 127)128 TRX per blockChain parameter #31 (getWitness127PayPerBlock)
Mempool orderingFirst-in-first-outNo auction-based MEV; no priority-fee bidding
Finality modelThreshold-based, deterministicOnce 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.

TermMeaning
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.
SlotA 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.
RoundOne 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 boundaryThe 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 blockA 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 signatureThe 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:

RoleVote rankActive?Can produce blocksCan submit ProposalCreateContractCan submit ProposalApproveContractApproval counted at expiryVoter reward
Active SRTop 27YesYesYesYesYesYes
SR Partner (SRP)28 – 127NoNoYesYes (recorded but filtered out)NoYes
SR Candidate (SRC)128+NoNoYesYes (recorded but filtered out)NoNo

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 terminology

The 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 see witness_* 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:

  1. Snapshot the per-cycle reward variable Vi for every SR, which records the SR's effective vote weight for the just-ended Maintenance Period and is used later for voter reward calculation.
  2. Apply pending vote deltas accumulated since the last boundary, updating each SR's running vote count.
  3. Re-rank all candidates by updated vote count.
  4. Promote the new top 27 to the active set, demote any falling below 27, and record the new role of every candidate.
  5. 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:

  1. Pulls transactions from its transaction mempool in the order it received them (FIFO).

  2. 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's validate() or execute() 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 a FAILED result 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.

  3. Adds metadata: parent block ID, the SR's own address, the new block's height, and the block timestamp.

  4. Signs the block with the configured localwitness private key. The signature lands in the witness_signature field.

  5. 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:

  1. 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.
  2. 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.
  3. 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 = NbSlot > hSlot passes.
  • But getNum(100') = 100 == headerNumberManager.pushBlock returns 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.

MechanismDetail
Threshold19 of 27 active SRs on mainnet; derived from SOLIDIFIED_THRESHOLD = 70 and the active SR set size
What countsAn SR counts only when it has itself produced a block at height H or above on this chain
What gets solidifiedThe block at H and all earlier blocks
Typical timeAbout 1 minute once block production is healthy
Worst caseBounded by the round length plus partition healing time
Where it's queryableThe 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 parentHash does 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:

RewardRecipientPer blockChain parameter
Block production rewardThe SR producing the block8 TRX (8,000,000 sun)#5 (getWitnessPayPerBlock)
Voter reward poolShared among the top 127 SRs by vote weight128 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/getchainparameters

In 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 0100) 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:

  1. Submit — Any SR, SRP, or SRC submits a ProposalCreateContract carrying a map of {parameter_id: new_value}. The proposal voting window is controlled by chain parameter #92 getProposalExpireTime, currently usually 3 days on Mainnet.
  2. Vote — Until expiry, any SR / SRP / SRC may submit ProposalApproveContract to 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.
  3. Tally and apply — At the expiration boundary, if ≥18 active-SR approvals are recorded, the proposal becomes APPROVED and its parameter changes are written to chain state in the same boundary block. If fewer, the proposal becomes DISAPPROVED. 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

APIDescription
wallet/getchainparametersList all chain parameters and current values
wallet/listwitnessesList the active 27 SRs
wallet/getnowblockLatest block (FullNode)
wallet/getblockbylimitnextRange of blocks by height
wallet/getnextmaintenancetimeTimestamp of the next Maintenance Period boundary
walletsolidity/getnowblockLatest solidified block (SolidityNode)
wallet/proposalcreateSubmit a proposal
wallet/proposalapproveApprove an open proposal
wallet/listproposalsList recent proposals and their states
wallet/votewitnessaccountVote for one or more SRs (replaces the prior allocation)
wallet/withdrawbalanceClaim accumulated voter rewards

Related resources