Skip to content

feat(vm): add node-level vm.constantCallTimeoutMs for constant calls#6719

Open
yanghang8612 wants to merge 2 commits intodevelopfrom
feat/constant-call-timeout
Open

feat(vm): add node-level vm.constantCallTimeoutMs for constant calls#6719
yanghang8612 wants to merge 2 commits intodevelopfrom
feat/constant-call-timeout

Conversation

@yanghang8612
Copy link
Copy Markdown
Collaborator

@yanghang8612 yanghang8612 commented Apr 28, 2026

What does this PR do?

Adds a node-level config vm.constantCallTimeoutMs (any positive integer; omit the property entirely to keep current behaviour) that extends the TVM execution-time window for the read-only RPC paths only — triggerconstantcontract, triggersmartcontract dispatched to view/pure functions, estimateenergy, eth_call, eth_estimateGas, and any other RPC routed through Wallet.callConstantContract. The block-processing deadline is unchanged.

When set, the configured value is used verbatim as the per-call deadline (no clamp against the network's maxCpuTimeOfOneTx, no cpuLimitInUsRatio scaling). When unset, constant calls fall back to the existing path that uses the network's maxCpuTimeOfOneTx.

Closes #6681.

Why are these changes required?

triggerconstantcontract / eth_call and the other constant-call RPCs are widely used for state queries and dry-runs but cap out at the same TVM deadline as block-processing (mainnet 80 ms). Operators currently have only --debug to extend this window, which also removes the block-processing timeout — unsafe for any node serving traffic, since it can desync from the network (#6266). This PR gives operators a scoped lever for the constant-call window without that side effect.

Design

  • Block-processing is structurally unaffected. The new branch is gated by isConstantCall in VMActuator.create() / call(), so it is unreachable from block validation — guaranteed by structure, not by convention.
  • Verbatim semantics. When the operator sets a value, it is used as the deadline as-is. No max(configured, networkMs) clamp, no cpuLimitInUsRatio scaling. Operators get exactly the budget they configured.
  • Opt-in detected by Config#hasPath. vm.constantCallTimeoutMs is intentionally absent from reference.conf, and the VmConfig field is excluded from ConfigBeanFactory auto-binding (@Setter(AccessLevel.NONE)) so the strict schema check doesn't require the path. vmSection.hasPath(...) then becomes a precise signal of "operator wrote this in config.conf". Same pattern as BlockConfig rejecting the legacy committee.proposalExpireTime location.
  • Validation only on opt-in. When the operator configures the value, it must be > 0; explicit 0 and negative values are rejected at config-load with IllegalArgumentException. Nodes that don't configure the property keep the existing default behaviour — no validation, no behaviour change.
  • Sub-frames inherit the deadline. Cross-contract simulation uses the existing Program plumbing (getVmShouldEndInUs() propagated to internal ProgramInvoke instances), so the override applies to deep call trees — the headline use case.

This PR has been tested by:

  • Unit Tests
    • VmConfigTest (4 new cases): default 0L when absent; any positive value accepted (1, 50, 500, 5000); explicit = 0 rejected; negative values rejected.
    • Existing VMActuator and Wallet callers' tests remain green.

Migration from --debug

Operators currently running with --debug purely to extend the constant-call window should switch to vm.constantCallTimeoutMs=<ms> once this lands. --debug additionally extends the block-processing timeout, which is unsafe for any node serving traffic (see #6266). Release notes will spell this out at both touchpoints.

@github-actions github-actions Bot requested a review from CodeNinjaEvan April 28, 2026 11:02
@halibobo1205 halibobo1205 added this to the GreatVoyage-v4.8.2 milestone Apr 28, 2026
@halibobo1205 halibobo1205 added the topic:vm VM, smart contract label Apr 28, 2026
@yanghang8612 yanghang8612 force-pushed the feat/constant-call-timeout branch 2 times, most recently from c414f1e to d8252da Compare May 6, 2026 03:29
Operators may set any positive integer to extend the per-call deadline for the constant-call APIs (triggerconstantcontract, triggersmartcontract dispatched to view/pure functions, estimateenergy, eth_call, eth_estimateGas, and others). The configured value is used verbatim. Replaces unsafe use of --debug, which also extends block-processing.
@yanghang8612
Copy link
Copy Markdown
Collaborator Author

Revised the implementation per the review thread on #6681 and force-pushed feat/constant-call-timeout (history collapsed from four commits to two: one feat(vm) + one test(vm)).

Major changes vs. the original four commits:

  1. Validation range relaxed. The [80, 500] ms bound is dropped. Any positive integer is accepted; only 0 (when explicitly written by the operator) and negative values are rejected.
  2. Concurrency cap removed. vm.constantCallMaxConcurrency, the Semaphore, the ThreadLocal reentrancy guard, and the WalletConstantCallThrottleTest suite are all gone. Operators handle throttling above the node (reverse proxy, API gateway, per-IP limits) — hard-gating at the node would false-positive on deployments that already throttle externally.
  3. Configured value is used verbatim. No more max(configured, networkMs) clamp and no cpuLimitInUsRatio scaling on the constant-call branch. The operator's configured ms is the per-call deadline, full stop.
  4. VmTimeoutPolicy helper removed. With the simplified policy, the deadline computation is a 4-line in-place patch in VMActuator.create() / call(). The helper class and its 12-case test suite are gone.
  5. Opt-in detection via hasPath. vm.constantCallTimeoutMs is intentionally absent from reference.conf, and the field is excluded from ConfigBeanFactory binding (@Setter(AccessLevel.NONE)). This pattern follows BlockConfig's rejection of the legacy committee.proposalExpireTime path: when a key is absent from reference.conf and isn't a bound bean property, Config#hasPath precisely reflects "operator wrote this in config.conf".

Net diff shrinks from 597+/9- across 11 files to ~107+/4- across 6 files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:vm VM, smart contract

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

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

4 participants