Witness permission separation

Use TRON's Account Permission Management to keep an SR's owner key offline while a hot key signs blocks.

ℹ️

Witness permission separation

Part of SR best practices — this page is the deep-dive walkthrough for the Witness permission separation practice.

📘

Prerequisites

By default, an SR account's witness_permission, active_permission, and owner_permission all authorize the same key — the SR's own address. A single private key therefore signs both blocks (validated against witness_permission) and balance-moving transactions (validated against owner / active). Leaking that key compromises block production and reward funds at once. TRON's Account Permission Management lets you split block production into a dedicated key — the owner key can stay on cold storage while a hot signing key only ever signs blocks.

This guide covers the on-chain permission update, the matching localwitness configuration on the node, and how to verify the delegation is working.

📘

Witness permission scope

Witness permission only covers block signing. Active permission still controls fund movement and account changes; treat it with the same care as the owner key. See Account permission management for the full permission model.

Why separate block production

  • Owner key stays offline. With witness permission delegated, the owner key is only needed when changing permissions, transferring rewards, or creating proposals — operations that can be batched and signed on a cold machine.
  • Hot signing key has limited blast radius. A leaked block-production key can only sign blocks. It cannot move TRX, vote, or update permissions. The attacker's options are reduced to disrupting block production, which is recoverable by reverting the permission update.
  • Standard practice. SRs operating in production typically delegate block production. See SR best practices.

Update the SR's account permissions

⚠️

Stop block production first

Stop the block-producing node before updating witness permission. Producing blocks while permissions are being changed risks signing with a key the network has just stopped accepting.

You can update the SR's permissions either through TRONSCAN's permission UI or by submitting an AccountPermissionUpdateContract:

Verify the witness_permission entry

Query the SR account with wallet/getaccount and inspect the witness_permission block:

BASE_URL=https://api.trongrid.io   # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl -X POST "${BASE_URL}/wallet/getaccount" \
  -H 'Content-Type: application/json' \
  -d '{"address":"TUZKijZ9Esy8JEkrqMpaVgtbDKKNA5p5CZ","visible":true}'
{
    "address": "TUZKijZ9Esy8JEkrqMpaVgtbDKKNA5p5CZ",
    ...
    "witness_permission": {
        "type": "Witness",
        "id": 1,
        "permission_name": "witness",
        "threshold": 1,
        "keys": [
            {
                "address": "TWDTKh7d3LzZhvBCrnWpJwGtsY2yw1NxFo",
                "weight": 1
            }
        ]
    },
    ...
}

The block above shows that SR TUZKij...p5CZ has delegated its block-production permission to the address TWDTKh...NxFo. Production blocks must now be signed by the private key of TWDTKh...NxFo.

Point the node at the delegated key

Set two fields in the SR node's config.conf:

# When the SR has delegated witness permission, set:
#   localWitnessAccountAddress = the SR account address
#   localwitness               = the private key of the delegated signing address

localWitnessAccountAddress = TUZKijZ9Esy8JEkrqMpaVgtbDKKNA5p5CZ

localwitness = [
  9191d6...13f818
]

# Alternative: use an encrypted keystore file instead of raw private key
#localwitnesskeystore = [
#  "localwitnesskeystore.json"
#]
FieldSet to
localWitnessAccountAddressThe SR's account address (the one ranked in the active 27 by votes).
localwitnessPrivate key of the delegated signing address. The node uses this key to sign blocks.
localwitnesskeystoreEncrypted keystore alternative to localwitness. Production deployments should prefer this (see SR best practices: protect keystore files).

If you did not delegate witness permission — meaning the SR account's witness_permission still authorizes its own address, the same key as owner_permission — leave localWitnessAccountAddress empty and configure localwitness (or localwitnesskeystore) with the SR account's own private key.

Start the node

Start a full node with the --witness flag to enable block production:

java -Xmx24g -XX:+UseConcMarkSweepGC -jar FullNode.jar --witness -c config.conf

For the full node deployment guide, see Deploy a fullnode or super-node.

When the node is scheduled to produce a block, it signs the block with localwitness and writes the signature into block_header.witness_signature.

Verify block production

Confirm the delegation is actually being used:

  • Node log. Look for produce block successfully lines emitted at your scheduled slots.
  • On-chain query. Use wallet/getblockbylimitnext to fetch recent blocks and check that the witness_address in blocks produced by your slot matches the SR account address.
  • TronScan. The SR's TronScan profile shows recent block production rate and detailed block production information.

Related resources