Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
fb8c82e
chore: ignore local env files and Claude local overrides
Jul 1, 2026
a7fa1ae
feat(tracers): add Parity/OpenEthereum trace_* RPC methods
Jul 1, 2026
85954a3
feat(server): gate the trace RPC namespace behind --rpc.enabletrace
Jul 1, 2026
c3456e4
docs: document trace_* API flag and known limitations in README
Jul 1, 2026
81c2c4f
eth/tracers: add TLOAD to vmTraceOpPushCount return-1 set
Jul 1, 2026
2c200b1
docs: fix TOML casing for enabletrace in README example
Jul 1, 2026
b7a77c8
eth/tracers: restore 5s defaultTraceTimeout, add 60s parity-specific …
Jul 1, 2026
d7cfef3
eth/tracers: use active precompile set for trace filter, covering BLS…
Jul 1, 2026
fd201ce
eth/tracers: fix comment — non-revert error emits result null, not om…
Jul 1, 2026
122845d
eth/tracers: fix potential integer overflow in buildParityStateDiff m…
Jul 1, 2026
f9ac0ab
docs: regenerate CLI docs to include rpc.enabletrace flag
Jul 1, 2026
4576885
eth/tracers: update tests for precompile-set parameter in convertCall…
Jul 1, 2026
6166712
eth/tracers: add tests for pruned node, underfunded sender, and trace…
Jul 1, 2026
505c9eb
eth/tracers: fix SonarCloud quality gate issues
Jul 1, 2026
6c0cd6f
eth/tracers: reduce duplication — parityExecInput struct and buildRep…
Jul 1, 2026
b99944c
eth/tracers: dedupe Parity block-replay setup into shared helper
Jul 2, 2026
c1123a3
eth/tracers: restructure parity code for CI quality gates
Jul 3, 2026
13b462b
eth/tracers: dedupe parity test harnesses into shared helpers
Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,8 @@ cmd/geth/geth
cmd/rlpdump/rlpdump
cmd/workload/workload
cmd/keeper/keeper

# Local environment secrets
.env
.env.local
CLAUDE.local.md
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,36 @@

Post `v0.3.0` release, bor uses a new command line interface (cli). The new-cli (located at `internal/cli`) has been built while keeping the flag usage similar to old-cli (located at `cmd/geth`) with a few notable changes. Please refer to [docs](./docs) section for the flag usage guide and example.

### Parity / OpenEthereum Trace API (`trace_*`)

Bor includes a Parity-compatible trace namespace (`trace_block`, `trace_transaction`,
`trace_replayTransaction`, `trace_replayBlockTransactions`, `trace_call`,
`trace_callMany`). These methods are **disabled by default** because they are
expensive and require an archive node.

Enable with the `--rpc.enabletrace` flag (or `JsonRPC.EnableTrace = true` in TOML):

```shell
bor server --config ./config.toml --rpc.enabletrace
```

Or in `config.toml`:

```toml
[jsonrpc]
enabletrace = true
```

**Requirements:**
- Archive node (`--gcmode archive`)
- Sufficient RPC timeout for deep blocks (`--rpc.evmtimeout` ≥ 60s recommended)

Check warning on line 70 in README.md

View check run for this annotation

Claude / Claude Code Review

README recommends --rpc.evmtimeout but that flag has no effect on tracers

The README's `--rpc.evmtimeout ≥ 60s recommended` line under the trace namespace is misleading: `--rpc.evmtimeout` maps to `RPCEVMTimeout`, which is only read by `eth_call` / `eth_simulate` / graphql — never by anything under `eth/tracers/`. Setting it has no effect on `trace_*` methods (they use their own `defaultParityTraceTimeout = 60s` internally). Consider dropping the line entirely (the 60s trace-phase default already gives operators what the README claims to want), or replacing it with th
Comment on lines +67 to +70

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 The README's --rpc.evmtimeout ≥ 60s recommended line under the trace namespace is misleading: --rpc.evmtimeout maps to RPCEVMTimeout, which is only read by eth_call / eth_simulate / graphql — never by anything under eth/tracers/. Setting it has no effect on trace_* methods (they use their own defaultParityTraceTimeout = 60s internally). Consider dropping the line entirely (the 60s trace-phase default already gives operators what the README claims to want), or replacing it with the knob that actually bounds a long trace call's wall-clock — the HTTP server write timeout (--http.timeout.write, default 30s).

Extended reasoning...

What is wrong

README.md:69 tells operators enabling the new Parity trace namespace to set --rpc.evmtimeout ≥ 60s. That flag is wired to ethconfig.RPCEVMTimeout and is consumed only by:

  • internal/ethapi/api.go (DoCalleth_call, eth_estimateGas)
  • internal/ethapi/simulate.go (eth_simulate)
  • graphql/graphql.go

grep -r RPCEVMTimeout eth/tracers/ returns zero hits. Neither debug_trace* nor the new trace_* methods read it.

How the trace path actually times out

The tracers ship their own constants:

  • eth/tracers/api.go:54defaultTraceTimeout = 5 * time.Second (used by debug_trace* when the caller does not set TraceConfig.Timeout).
  • eth/tracers/parity.go:28defaultParityTraceTimeout = 60 * time.Second (used by parityTraceConfig for every trace_* call, since the Parity RPC methods do not expose Timeout to the caller).

So the trace phase is already capped at 60s internally, regardless of --rpc.evmtimeout. The only external knob that governs a long trace_* call is the HTTP server write timeout (--http.timeout.write, default 30s), which will cut the RPC response off well before the 60s tracer cap on default settings.

Step-by-step proof

  1. Operator follows README: bor server --rpc.enabletrace --rpc.evmtimeout 60s --gcmode archive.
  2. --rpc.evmtimeout 60s sets JsonRPC.RPCEVMTimeout = 60s in the config, threaded into ethconfig.Config.RPCEVMTimeout.
  3. Operator calls trace_replayBlockTransactions for a heavy historical block.
  4. Request routes to TraceAPI.ReplayBlockTransactionsreplayBlockTransactionsbuildReplayResultparityTraceTxtraceTx(cfg = parityTraceConfig(userCfg)).
  5. In parityTraceConfig (parity.go:184), cfg.Timeout is set to defaultParityTraceTimeout.String() (60s). RPCEVMTimeout is not read anywhere on this path.
  6. In traceTx the timeout comes from cfg.Timeout — the 60s constant — not from api.b.RPCEVMTimeout().
  7. Meanwhile the HTTP handler enforces its own write timeout (default 30s, jsonrpc.timeouts.write); if the reply is not written in time the client sees a broken connection well before the 60s tracer cap.

The operator has set a flag that changes literally nothing about their trace timeouts.

Impact

Documentation-only. The trace namespace works correctly out of the box because the internal 60s default is already what the README claims to be recommending. Nothing crashes, no wrong data is returned; the advice is simply a no-op for the namespace it targets. The practical harm is that an operator debugging a hung trace_* call will look at the flag they set (--rpc.evmtimeout) instead of the flag that actually matters (--http.timeout.write).

How to fix

Two good options in README.md (and in the PR description, which repeats the same line under "Recommended companion flags"):

  • Drop the --rpc.evmtimeout bullet entirely. The internal defaultParityTraceTimeout = 60s already gives the intended behavior.
  • Replace it with --http.timeout.write (default 30s), which is the real ceiling on a long trace_* call. Suggested wording: "Sufficient HTTP write timeout for deep blocks (--http.timeout.write ≥ 60s recommended, since heavy trace_replay* calls can take longer than the 30s default before the internal 60s trace cap trips)."

Severity

nit — documentation error, not a code-correctness bug. Merging as-is does not break the feature. Worth fixing before release notes go out so operators are not chasing a no-op flag.


**Known limitations vs Polygon Erigon:**
- `trace_call`/`trace_callMany` on underfunded simulated senders returns an error
instead of a bailout trace (gas bailout not yet implemented).
- `trace_block` omits the state-sync pseudo-transaction for pre-Madhugiri blocks
(< 80,084,800 on mainnet); post-Madhugiri blocks are fully supported.

### Latest Config Reference

For the latest canonical TOML config options, refer to:
Expand Down
2 changes: 2 additions & 0 deletions docs/cli/chain_sethead.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ The ```chain sethead <number>``` command sets the current chain to a certain blo

- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.

- ```yes```: Force set head (default: false)
4 changes: 3 additions & 1 deletion docs/cli/debug_block.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ The ```bor debug block <number>``` command will create an archive containing tra

- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)

- ```output```: Output directory
- ```output```: Output directory

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.
4 changes: 3 additions & 1 deletion docs/cli/debug_pprof.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ The ```debug pprof <enode>``` command will create an archive containing bor ppro

- ```seconds```: seconds to profile (default: 2)

- ```skiptrace```: Skip running the trace (default: false)
- ```skiptrace```: Skip running the trace (default: false)

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.
1 change: 1 addition & 0 deletions docs/cli/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ devfakeauthor = false
rangelimit = 0
allow-unprotected-txs = false
enabledeprecatedpersonal = false
enabletrace = false
"txsync.defaulttimeout" = "20s"
"txsync.maxtimeout" = "1m0s"
accept-preconf-tx = false
Expand Down
2 changes: 2 additions & 0 deletions docs/cli/peers_add.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ The ```peers add <enode>``` command joins the local client to another remote pee

- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.

- ```trusted```: Add the peer as a trusted (default: false)
4 changes: 3 additions & 1 deletion docs/cli/peers_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ The ```peers list``` command lists the connected peers.

## Options

- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)
- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.
2 changes: 2 additions & 0 deletions docs/cli/peers_remove.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ The ```peers remove <enode>``` command disconnects the local client from a conne

- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.

- ```trusted```: Add the peer as a trusted (default: false)
4 changes: 3 additions & 1 deletion docs/cli/peers_status.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ The ```peers status <peer id>``` command displays the status of a peer by its id

## Options

- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)
- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.
4 changes: 3 additions & 1 deletion docs/cli/removedb.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ The ```bor removedb``` command will remove the blockchain and state databases at

- ```address```: Address of the grpc endpoint (default: 127.0.0.1:3131)

- ```datadir```: Path of the data directory to store information
- ```datadir```: Path of the data directory to store information

- ```token```: Bearer token to authenticate with the bor gRPC server (matches --grpc.token on the server). Falls back to the BOR_GRPC_TOKEN environment variable when unset.
2 changes: 2 additions & 0 deletions docs/cli/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ The ```bor server``` command runs the Bor client.

- ```rpc.enabledeprecatedpersonal```: Enables the (deprecated) personal namespace (default: false)

- ```rpc.enabletrace```: Enables the Parity-compatible trace namespace (trace_block, trace_transaction, trace_call, trace_callMany, trace_replayTransaction, trace_replayBlockTransactions) (default: false)

- ```rpc.evmtimeout```: Sets a timeout used for eth_call (0=infinite) (default: 5s)

- ```rpc.gascap```: Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite) (default: 50000000)
Expand Down
40 changes: 2 additions & 38 deletions eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1004,49 +1004,13 @@ func containsTx(block *types.Block, hash common.Hash) bool {
// TraceTransaction returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
found, _, blockHash, blockNumber, index := api.backend.GetCanonicalTransaction(hash)
if !found {
// Warn in case tx indexer is not done.
if !api.backend.TxIndexDone() {
return nil, ethapi.NewTxIndexingError()
}
// Only mined txes are supported
return nil, errTxNotFound
}
// It shouldn't happen in practice.
if blockNumber == 0 {
return nil, errors.New("genesis is not traceable")
}
reexec := defaultTraceReexec
if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
block, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash)
if err != nil {
return nil, err
}
tx, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
in, release, err := api.canonicalTxTraceEnv(ctx, hash, config)
if err != nil {
return nil, err
}
defer release()

txctx := &Context{
BlockHash: blockHash,
BlockNumber: block.Number(),
TxIndex: int(index),
TxHash: hash,
// This field is only used for bor transactions. Use block gas used as state-sync is
// always the last tx.
CumulativeGasUsed: block.GasUsed(),
LogIndex: len(statedb.Logs()),
}

msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee())
if err != nil {
return nil, err
}
res, _, err := api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config, nil)
res, _, err := api.traceTx(ctx, in.tx, in.msg, in.txctx, in.vmctx, in.statedb, config, nil)
return res, err
}

Expand Down
Loading
Loading