Consensus and DPoS

How TRON's 27 Super Representatives produce blocks under Delegated Proof of Stake, how blocks become irreversible, what happens at each scheduled maintenance update, 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 lengthNormally 81 seconds27 slots × 3 s when the round does not cross a maintenance update and no SR misses a slot
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
Post-maintenance block-production gapTwo slotsAfter a maintenance-triggering block, the next two 3-second slots are skipped
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

The Maintenance Period, block-production reward, and voter reward are dynamic chain parameters that can be changed through proposals. Query wallet/getchainparameters for all chain parameters and their current 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. Under the current Mainnet resource model, staking 1 TRX grants 1 TP, and 1 TP authorizes one vote.
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 normal production rotation of the 27 active SRs. When the rotation does not cross a maintenance update and no SR misses a slot, each SR has one slot and the round takes 81 seconds. A maintenance update can change the active set and order and introduces two skipped slots, so the 81-second duration does not apply across that point.
Maintenance Period (MP)The recurring interval between scheduled maintenance updates, currently 6 hours on Mainnet (MAINTENANCE_TIME_INTERVAL, configurable by proposal). The active SR set and production order remain stable between updates.
Scheduled maintenance timeA timestamp threshold stored in chain state. The first block whose timestamp reaches or exceeds the threshold triggers maintenance processing.
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. With the current Mainnet setting getAllowOptimizeBlackHole=1, java-tron records this fee directly as burned instead of crediting the black-hole account. It cannot be reclaimed even if the account later stops being an SR and functions as the network's Sybil-resistance gate for entering the producer pool.

Once registered, an SRC accumulates votes. At each scheduled maintenance update, 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. As the rankings change, candidates can move among the active-SR, SR-Partner, and other-candidate tiers.

📘

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 as accounts cast or revoke them, and the active set is recomputed from the latest tally at each scheduled maintenance update.

How votes work

A vote is a non-transferable allocation of TRON Power (TP) from one account to one or more SR candidates. Mainnet currently has getAllowNewResourceModel=0, so staking TRX for Bandwidth or Energy through FreezeBalanceV2Contract grants 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 available TP.

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 a maintenance update

Votes change continuously, but the resulting active SR set is recomputed only when a block triggers scheduled maintenance. The network then does the following, in order:

  1. Update each SR's cumulative per-vote reward index Vi, adding the just-ended period's voter reward divided by that SR's effective vote count for later voter-reward calculations.
  2. Apply pending vote deltas accumulated since the previous maintenance update, 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.

These updates are applied while the maintenance-triggering block is processed. The next scheduled block uses the updated active SR set and production order.

Effects of mid-cycle vote changes

The active SR set remains unchanged between maintenance updates. Vote changes made during a Maintenance Period therefore do not change the current block producers; they are tallied at the next scheduled maintenance update and used to determine the active set for the next Maintenance Period. Voter rewards use separate per-cycle account-vote accounting rules; see Voting for SRs for details.


Block production schedule

TRON normally schedules one block-production slot every 3 seconds, in an order derived from the active set established at the most recent scheduled maintenance update. When the rotation does not cross a maintenance update and every SR produces on schedule, the 27 SRs complete one round in 81 seconds. A maintenance update can change the active set and order and introduces two skipped slots, so the 81-second duration does not apply across that point.

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 production order remains unchanged between maintenance updates, even as votes continue to shift. At the next scheduled maintenance update, the network uses the updated ranking to determine the production order for the next Maintenance Period.

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 may move it out of the active 27 at the next scheduled maintenance update. 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.

Post-maintenance block-production gap

With the current Mainnet parameter, scheduled maintenance occurs at 6-hour intervals. The first block whose timestamp reaches or exceeds the next scheduled maintenance time triggers maintenance processing. After that block is applied, the scheduler skips the next two 3-second slots (MAINTENANCE_SKIP_SLOTS = 2). If no SR misses a slot and there is no additional network delay, the next planned block has a timestamp 9 seconds after the maintenance-triggering block and uses the updated active SR set and production order. Protocol-skipped slots are not assigned to an SR and are not recorded as missed production.


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 may fall out of the active 27 at the next scheduled maintenance update.

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 × 28792 ≈ 3.69M TRX (28,792 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

Current network-parameter values — including block rewards, resource prices, and enabled TVM features — live in chain state. The java-tron protocol implementation still defines the parameter IDs and validates permitted ranges, fork or version prerequisites, dependencies, and one-way activation rules. Active-SR proposals can modify a value only when those checks allow it; not every setting is arbitrary or reversible.

A proposal accepts approvals during its voting window and is settled at expiry. It goes through three stages:

  1. Submit — Any SR, SRP, or SRC submits a ProposalCreateContract carrying a map of {parameter_id: new_value}. Before accepting the transaction, a node validates the proposed values against the parameter ranges, fork prerequisites, and dependencies implemented by its java-tron version. 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 active SRs in effect before the expiration update are counted toward the threshold.
  3. Tally and apply — The first block whose timestamp reaches or exceeds the proposal's expiration time tallies the approvals before updating the active SR set. If ≥18 eligible approvals are recorded, the proposal becomes APPROVED and its parameter changes apply to subsequent blocks. 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 common network parameters and how to query them, 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/getnextmaintenancetimeNext scheduled maintenance time
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