Skip to content

[Feature] Add a node-level configuration to control the TVM execution time limit for constant calls #6681

@yanghang8612

Description

@yanghang8612

Background

In the TRON network, the triggerconstantcontract API (and the Ethereum-compatible eth_call) is widely used for constant calls — including state queries via view/pure functions and transaction simulation (dry-runs). However, both are constrained by the TVM execution time limit (mainnet default: 80ms). When executing complex contract logic or intensive state access, this can lead to out_of_time exceptions, reducing the reliability of development tools, data services, and analytics platforms.

Running the FullNode with the --debug flag can remove the TVM timeout restriction for constant calls, but it also removes the timeout limit for transactions during normal block processing. As discussed in #6266, this can cause the local execution result to diverge from the result carried in the block (the block may report OUT_OF_TIME while the local node does not), which in turn causes the node to stop syncing. --debug is therefore not suitable for production nodes.

This issue supersedes #6288. After extensive discussion in that thread, the community reached consensus that a node-level configuration is preferable to the originally proposed request-body parameter approach. This new issue reflects the revised direction.

Related issues: #6266, #6288

Rationale

Why should this feature exist?

Node operators should be able to extend the TVM execution time window for constant calls only, without affecting block validation behavior. This would:

  • Improve the stability of off-chain analysis tools and data services
  • Prevent false negatives when querying or simulating complex contracts
  • Reduce misleading error codes that confuse developers
  • Avoid the sync-halt side effect of --debug

What are the use-cases?

  • Data services performing bulk state queries via contract calls
  • Deep cross-contract call simulation
  • Simulating complex logic (e.g., loops or large mappings) that exceed the default execution window

Why a node-level config instead of a request parameter?

As discussed in #6288, we decided against adding a timeout_ms field to the request body, for the following reasons:

  • API standard compatibility. Adding a non-standard field to eth_call would diverge from the Ethereum JSON-RPC specification and complicate integration for Ethereum tooling (ref).
  • Separation of responsibility. Execution policy belongs to the node operator, not the caller. Operators that need extended simulation windows opt in explicitly; public-facing nodes keep the default (ref).
  • No consensus risk. Constant calls are not broadcast on-chain, so a node-level knob does not risk SR consensus divergence (ref).
  • Backward compatible. No API surface change, no SDK updates required.

Specification

Introduce a new node configuration option (name TBD, e.g. vm.constantCallTimeoutMs) in config.conf:

vm {
  # Max TVM execution time (ms) for constant calls
  # (triggerconstantcontract / eth_call). Default: 80.
  # Must be within [80, MAX_ALLOWED].
  constantCallTimeoutMs = 80
}

Behavior:

  • Applies only to constant calls (triggerconstantcontract, eth_call, and equivalent read-only execution paths).
  • Does not affect TVM execution during block processing or transaction broadcasting.
  • A strict upper bound (e.g. 500ms) must be enforced to bound DoS risk.
  • The effective timeout used for a given call should be observable (e.g. logged / returned in diagnostics) so operators can reason about behavior.

Safeguards

Regardless of the exact value chosen, extending the window increases per-call cost. The implementation should include:

  • A hard upper bound on the configurable value.
  • Rate limiting / concurrency cap for constant calls, especially when the configured timeout exceeds the default.
  • Clear operator-facing documentation describing the trade-off and recommended values for public vs. private node deployments.

Test Specification

  • Unit tests covering: default behavior unchanged; custom timeout respected for constant calls; block-processing timeout unchanged regardless of the new config.
  • Integration tests verifying that a node with an extended constantCallTimeoutMs still syncs correctly against the main network (no OUT_OF_TIME divergence like --debug).
  • Stress tests under concurrent constant-call load at the configured upper bound.

Scope Of Impact

  • Non-breaking. No API signature change; existing clients and SDKs unaffected.
  • TVM executor must branch on call context (block processing vs. constant call) when selecting the timeout.
  • Operator documentation and release notes must describe the new option and its risks.

Implementation

Tentative outline:

  • Add the config field and wire it through Args / VM config.
  • Plumb a per-invocation timeout into the constant-call execution path (TVM executor) without touching the block-processing path.
  • Enforce the upper bound at config-load time; reject invalid values with a clear error.
  • Add rate-limiting hooks around constant-call execution.

Are you willing to implement this feature?

Yes.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions